1. 程式人生 > 實用技巧 >Java實現 LeetCode第197場周賽 (題號5460,5461,5211,5463)

Java實現 LeetCode第197場周賽 (題號5460,5461,5211,5463)

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,請你找出從起點到終點成功概率最大的路徑,並返回其成功概率。

如果不存在從startend的路徑,請返回 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 }