Java實現 LeetCode第197場周賽 (題號5460,5461,5211,5463)
阿新 • • 發佈:2020-07-12
5460. 好數對的數目
給你一個整數陣列nums
。
如果一組數字(i,j)
滿足nums[i]
==nums[j]
且i
<j
,就可以認為這是一組好數對。
返回好數對的數目。
示例 1:
輸入:nums = [1,2,3,1,1,3] 輸出:4 解釋:有 4 組好數對,分別是 (0,3), (0,4), (3,4), (2,5) ,下標從 0 開始
示例 2:
輸入:nums = [1,1,1,1] 輸出:6 解釋:陣列中的每組數字都是好數對
示例 3:
輸入:nums = [1,2,3] 輸出:0
提示:
1 <= nums.length <= 100
1 <= nums[i] <= 100
1 class Solution { 2 public int numIdenticalPairs(int[] nums) { 3 int count = 0; 4 for (int i=0;i<nums.length;i++){ 5 for (int j=i+1;j<nums.length;j++){ 6 if(nums[i]==nums[j]){ 7 ++count; 8 } 9 }10 } 11 return count; 12 } 13 }
又找到了一種簡單方法
1 class Solution { 2 //一個數出現了n次的話,這個數的好數對就是n*(n-1)/2 3 public int numIdenticalPairs(int[] nums) { 4 5 int[] temp = new int[101]; 6 for(int i:nums){ 7 ++temp[i]; 8 } 9 int count=0;10 for(int i:temp){ 11 if(i==0){ 12 continue; 13 }else{ 14 count+=(i*(i-1)/2); 15 } 16 } 17 return count; 18 19 20 21 } 22 }
5461. 僅含 1 的子串數
給你一個二進位制字串s
(僅由 '0' 和 '1' 組成的字串)。
返回所有字元都為 1 的子字串的數目。
由於答案可能很大,請你將它對 10^9 + 7 取模後返回。
示例 1:
輸入:s = "0110111" 輸出:9 解釋:共有 9 個子字串僅由 '1' 組成 "1" -> 5 次 "11" -> 3 次 "111" -> 1 次
示例 2:
輸入:s = "101" 輸出:2 解釋:子字串 "1" 在 s 中共出現 2 次
示例 3:
輸入:s = "111111" 輸出:21 解釋:每個子字串都僅由 '1' 組成
示例 4:
輸入:s = "000" 輸出:0
提示:
s[i] == '0'
或s[i] == '1'
1 <= s.length <= 10^5
1 class Solution { 2 //這個題得思路是找到1得多少個子串 3 //如果6個1:字串得數量為6+5+4+3+2+1 4 /* 5 一位字串:6 6 兩位字串:5個,從開始走假設六位數為123456 7 12 23 34 45 56 8 每兩位猜錯一個,到最後一個正好比1位字串少一個 9 三位字串:4個 123 234 345 456 一樣的 10 11 */ 12 13 public int numSub(String s) { 14 String[] strs = s.split("0"); 15 int[] num = new int [100000+1]; 16 //先按照0分解,看看每一塊1都有多少位 17 for (String ss:strs){ 18 ++num[ss.length()]; 19 } 20 int res = 0; 21 //從1位開始,0位是不作數得 22 for (int i=1;i<num.length;i++){ 23 if(num[i]==0) continue;i 24 //如果是奇數就 25 //例子: 26 //你可以帶進去,相當於高斯求和得意思 27 // (i+1)/2*i *num[i] 28 // 下面我寫的可能很繁瑣,其實就是為了取餘防止超 29 if((i&1)==1){ 30 long temp = ((i+1)/2)%1000000007l*i; 31 temp=temp%1000000007*num[i]%1000000007; 32 res=(res+(int)temp)%1000000007; 33 } else{ 34 //你可以帶進去,相當於高斯求和得意思 35 //(i+1)/2*i*num[i] 36 long temp = (i+1)%1000000007l*i/2%1000000007; 37 38 temp=temp%1000000007*num[i]%1000000007; 39 res=(res+(int)temp)%1000000007; 40 41 } 42 } 43 return res; 44 } 45 }
5211. 概率最大的路徑
給你一個由n
個節點(下標從 0 開始)組成的無向加權圖,該圖由一個描述邊的列表組成,其中edges[i] = [a, b]
表示連線節點 a 和 b 的一條無向邊,且該邊遍歷成功的概率為succProb[i]
。
指定兩個節點分別作為起點start
和終點end
,請你找出從起點到終點成功概率最大的路徑,並返回其成功概率。
如果不存在從start
到end
的路徑,請返回 0。只要答案與標準答案的誤差不超過1e-5,就會被視作正確答案。
示例 1:
輸入:n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2 輸出:0.25000 解釋:從起點到終點有兩條路徑,其中一條的成功概率為 0.2 ,而另一條為 0.5 * 0.5 = 0.25
示例 2:
輸入:n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2 輸出:0.30000
示例 3:
輸入:n = 3, edges = [[0,1]], succProb = [0.5], start = 0, end = 2 輸出:0.00000 解釋:節點 0 和 節點 2 之間不存在路徑
提示:
2 <= n <= 10^4
0 <= start, end < n
start != end
0 <= a, b < n
a != b
0 <= succProb.length == edges.length <= 2*10^4
0 <= succProb[i] <= 1
- 每兩個節點之間最多有一條邊
1 class Solution { 2 3 public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) { 4 5 double error = 1e-6; 6 Map<Integer, List<Node>> map = new HashMap<>(); 7 //把當前得結構放進去 8 for (int i = 0; i < edges.length; i++) { 9 int[] e = edges[i]; 10 if (!map.containsKey(e[0])) { 11 map.put(e[0], new ArrayList<>()); 12 } 13 14 if (!map.containsKey(e[1])) { 15 map.put(e[1], new ArrayList<>()); 16 } 17 //這裡是無向圖,要正反放入 18 map.get(e[0]).add(new Node(e[0], e[1], succProb[i])); 19 map.get(e[1]).add(new Node(e[1], e[0], succProb[i])); 20 } 21 double[] dp = new double[n]; 22 dp[start] = 1; 23 //BFS搜尋 24 Queue<Integer> q = new ArrayDeque<>(); 25 q.add(start); 26 while (!q.isEmpty()) { 27 int cur = q.poll(); 28 //找到以當前結點連線得點 29 for (Node node : map.getOrDefault(cur, new ArrayList<>())) { 30 //迴圈,看看能不能讓成功率更高,如果成功率更高,就可以選用, 31 //把點放入node 32 if (dp[cur] * node.prob > dp[node.to] + error) { 33 q.add(node.to); 34 //儲存當前點得成功率 35 dp[node.to] = dp[cur] * node.prob; 36 } 37 } 38 } 39 return dp[end]; 40 } 41 42 class Node { 43 int from; 44 int to; 45 double prob; 46 public Node(int from, int to, double prob) { 47 this.from = from; 48 this.to = to; 49 this.prob = prob; 50 } 51 } 52 }
5463. 服務中心的最佳位置
一家快遞公司希望在新城市建立新的服務中心。公司統計了該城市所有客戶在二維地圖上的座標,並希望能夠以此為依據為新的服務中心選址:使服務中心到所有客戶的歐幾里得距離的總和最小。
給你一個數組positions
,其中positions[i] = [xi, yi]
表示第i
個客戶在二維地圖上的位置,返回到所有客戶的歐幾里得距離的最小總和 。
換句話說,請你為服務中心選址,該位置的座標[xcentre, ycentre]
需要使下面的公式取到最小值:
與真實值誤差在10^-5
之內的答案將被視作正確答案。
示例 1:
輸入:positions = [[0,1],[1,0],[1,2],[2,1]] 輸出:4.00000 解釋:如圖所示,你可以選 [xcentre, ycentre] = [1, 1] 作為新中心的位置,這樣一來到每個客戶的距離就都是 1,所有距離之和為 4 ,這也是可以找到的最小值。
示例 2:
輸入:positions = [[1,1],[3,3]] 輸出:2.82843 解釋:歐幾里得距離可能的最小總和為 sqrt(2) + sqrt(2) = 2.82843
示例 3:
輸入:positions = [[1,1]] 輸出:0.00000
示例 4:
輸入:positions = [[1,1],[0,0],[2,0]] 輸出:2.73205 解釋:乍一看,你可能會將中心定在 [1, 0] 並期待能夠得到最小總和,但是如果選址在 [1, 0] 距離總和為 3 如果將位置選在 [1.0, 0.5773502711] ,距離總和將會變為 2.73205 當心精度問題!
示例 5:
輸入:positions = [[0,1],[3,2],[4,5],[7,6],[8,9],[11,1],[2,12]] 輸出:32.94036 解釋:你可以用 [4.3460852395, 4.9813795505] 作為新中心的位置
提示:
1 <=positions.length <= 50
positions[i].length == 2
0 <=positions[i][0],positions[i][1] <= 100
1 class Solution { 2 //這個題當時周賽沒做出來,思路很新穎,又學習到了 3 public double getMinDistSum(int[][] positions) { 4 //先用所有點把最平均得那個點求出來 5 double[] current_point = new double[2]; 6 for (int i = 0; i < positions.length; i++) { 7 current_point[0] += positions[i][0]; 8 current_point[1] += positions[i][1]; 9 } 10 current_point[0] /= positions.length; 11 current_point[1] /= positions.length; 12 //求出最平均得點,到所有點得距離 13 double minimum_distance = distSum(current_point, positions, positions.length); 14 //迪傑斯特拉,看看那個點會比當前點更近距離 15 int k = 0; 16 while (k < positions.length) { 17 //這裡不能是當前點,k為迴圈的點,如果相等的話,說明有相同的點 18 for (int i = 0; i < positions.length && i != k; i++) { 19 double[] newpoint = new double[2]; 20 newpoint[0] = positions[i][0]; 21 newpoint[1] = positions[i][1]; 22 double newd = distSum(newpoint, positions, positions.length); 23 if (newd < minimum_distance) { 24 minimum_distance = newd; 25 current_point[0] = newpoint[0]; 26 current_point[1] = newpoint[1]; 27 } 28 } 29 k++; 30 } 31 //然後就是通過一點一點得找到更近得點 32 double test_distance = 1000; 33 int flag = 0; 34 //四個方向 35 double[][] test_point = { { -1.0, 0.0 }, { 0.0, 1.0 }, { 1.0, 0.0 }, { 0.0, -1.0 } }; 36 //當距離小於0.0001的時候,就認為就是最短點了 37 while (test_distance > 0.0001) { 38 flag = 0; 39 for (int i = 0; i < 4; i++) { 40 double[] newpoint = new double[2]; 41 //四個方向去找 42 newpoint[0] = current_point[0] + (double) test_distance * test_point[i][0]; 43 newpoint[1] = current_point[1] + (double) test_distance * test_point[i][1]; 44 double newd = distSum(newpoint, positions, positions.length); 45 if (newd < minimum_distance) { 46 //如果有更近得點說明找對了方向,此次迴圈就可以跳過去了 47 minimum_distance = newd; 48 current_point[0] = newpoint[0]; 49 current_point[1] = newpoint[1]; 50 flag = 1; 51 break; 52 } 53 } 54 if (flag == 0) 55 test_distance /= 2; 56 } 57 return minimum_distance; 58 } 59 //求某個點到所有點得和 60 double distSum(double[] p, int[][] arr, int n) { 61 double sum = 0; 62 for (int i = 0; i < n; i++) { 63 double distx = Math.abs(arr[i][0] - p[0]); 64 double disty = Math.abs(arr[i][1] - p[1]); 65 sum += Math.sqrt((distx * distx) + (disty * disty)); 66 } 67 68 return sum; 69 } 70 }