日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

719. Find K-th Smallest Pair Distance

發布時間:2023/12/10 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 719. Find K-th Smallest Pair Distance 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1 題目理解
  • 2 分析思路
    • 2.1 桶排序
    • 2.2 二分+動態規劃
    • 2.3 用堆實現
  • 3相似題目786
  • 3.1 二分
    • 3.2 堆

1 題目理解

輸入:一個int數組nums,一個數字k
輸出:返回所有數字對中,數字對距離第k小的距離。
規則:一個數組中兩兩配對計算差值得到距離。距離值從小到大排序,第k位置的元素就是返回值。
例如
Input:
nums = [1,3,1]
k = 1
Output: 0
所有的配對距離是:
(1,3) -> 2
(1,1) -> 0
(3,1) -> 2
所有距離中從小到大排序,第1個是0,所以返回0。

Note:

2 <= len(nums) <= 10000.
0 <= nums[i] < 1000000.
1 <= k <= len(nums) * (len(nums) - 1) / 2.

2 分析思路

內容來源于花花醬。

2.1 桶排序

最直接的想法是用兩個for循環計算每個匹配對的距離,然后對距離進行排序。返回第k個元素 。排序算法選擇桶排序,加快速度。int[] distance記錄距離出現的次數。distance[0]表示有幾個配對的距離為0。

class Solution {public int smallestDistancePair(int[] nums, int k) {Arrays.sort(nums);int n = nums.length;int max = nums[n-1];int[] distance = new int[max+1];for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){distance[nums[j] - nums[i]]++;}}for(int i = 0;i<max;i++){k -= distance[i];if(k<=0){return i;}}return 0;} }

時間復雜度O(n2max)O(n^2max)O(n2max)

2.2 二分+動態規劃

我們先對數組nums排序。
返回值最小值是0,最大值=nums最大值-nums最小值。
用二分法查找返回值,也就是距離。
例如m=3,我們需要查找有多少個配對的距離小于等于3。
查找的方法使用動態規劃。
設dp[0] 為所有和nums[0]配對的距離小于等于3,有多少個。
dp[1]為所有和nums[0],nums[1]的配對距離小于等于3,有多少個。

dp[n-1]表示所有配對中距離小于等于3,有多少個。
例如nums={1,1,3,5,8}。
最開始,i=0,j=0,
nums[0] - nums[0] =0<=m,成立,j++;
nums[1]-nums[0]=1-1=0<=m,成立,j++;
nums[2]-nums[0]=3-1=2<=m,成立,j++;
nums[3]-nums[0]=5-1=4<=m,不成立,退出循環,因為數組是有序的,再比較下去,距離只會越來越大。
那么dp[0] = j-i-1=3-0-1=2,表示所有和nums[0]配對中,有2個配對的距離<=m。

接著計算i=1,此時j不需要從0開始。

配對(0,2)在上一步已經計算了,配對(1,2)的距離一定<=m。
因為nums[2]-nums[0]<=m,在上一步已經計算過了,而nums[1]>nums[0],同樣的數減去一個更大的數,差只能更小。
所以j不需要從0開始。

j=3,nums[3]-nums[1]=5-1=4<=m,不成立,退出循環。
dp[1] = dp[0] + (j-i-1)=3,表示所有和nums[0]、nums[1]配對中,有3個配對的距離<=m。

接著計算i=4,j=3。

class Solution {public int smallestDistancePair(int[] nums, int k) {Arrays.sort(nums);int n = nums.length;int l = 0;int r = nums[n-1]-nums[0];while(l<=r){int m = l+((r-l)>>1);if(countNumber(nums,m)>=k){r = m - 1;}else{l = m + 1;}}return l;}private int countNumber(int[] nums,int m){int j = 0;int n = nums.length;int[] dp = new int[n];for(int i=0;i<n;i++){while(j<n && nums[j]-nums[i]<=m) j++;dp[i] = ( i==0? (j-i-1) : dp[i-1]+(j-i-1));}return dp[n-1];} }

時間復雜度O(nlogn)O(nlogn)O(nlogn),n應該是數組長度和數組最大值之間的最大值。當然最后的代碼還可以做空間優化。

2.3 用堆實現

參考力扣
首先將數組排序,排序之后,相鄰元素的差最小。先將nums[i]和nums[i+1],放入堆中,之后再依次將nums[i]和nums[i+2] nums[i]和nums[i+3]放入堆中 …
時間復雜度O((k+N)lgN),時間復雜度過高。

class Solution {public int smallestDistancePair(int[] nums, int k) {Arrays.sort(nums);PriorityQueue<Node> heap = new PriorityQueue<Node>(nums.length,Comparator.<Node> comparingInt(node -> nums[node.nei] - nums[node.root]));int n = nums.length;for(int i=0;i<n-1;i++){heap.offer(new Node(i,i+1));}Node node = null;for(;k>0;k--){node = heap.poll(); if(node.nei+1<n){heap.offer(new Node(node.root,node.nei+1));}}return nums[node.nei]- nums[node.root];}class Node {int root;int nei;Node(int r, int n) {root = r;nei = n;}}}

3相似題目786

3.1 二分

雖說相似,沒有找到規律還是理解不了的。即使找到規律了也不一定會數數,在O(n)時間復雜度內。

class Solution {public int[] kthSmallestPrimeFraction(int[] A, int K) {double l = 0;double r = 1.0;int[] answer = new int[2];while(l<r){double m = (l+r)/2;int[] res = countSmallerOrEqual(A,m);if(res[0] == K){answer[0] = res[1];answer[1] = res[2];break;}else if(res[0]>=K){r = m;}else{l = m;}}return answer;}private int[] countSmallerOrEqual(int[] A,double m){int count = 0;int p = 0,q = 1;int i=0;for(int j=1;j<A.length;j++){while(A[i]<=m*A[j]) i++;count += i;if(i>0){i=i-1;if(p*A[j]<q*A[i]){p = A[i];q = A[j];}}}return new int[]{count, p, q};}}

對于countSmallerOrEqual函數不知道怎么寫,可以先用兩個for循環來寫。會發現i的循環可以提取出來。因為A數組是遞增的。例如[1,2,3,5]。如果1/2滿足條件,那么1/3一定滿足條件。因為分子不變,分母增加,數值會越來越小。

private int[] countSmallerOrEquals(int[] A ,double m){int count = 0;int p = 0,q = 1;for(int j=1;j<A.length;j++){int i=0;for(;i<j;i++){if(A[i]>m*A[j]){break;}}count += i;i=i-1;if(p*A[j]<q*A[i]){p = A[i];q = A[j];}}return new int[]{count, p, q};}

3.2 堆

class Solution {public int[] kthSmallestPrimeFraction(int[] A, int k) {int[] answer = new int[2];PriorityQueue<int[]> pq = new PriorityQueue<int[]>((a, b) ->A[a[0]] * A[b[1]] - A[a[1]] * A[b[0]]);for(int i=1;i<A.length;i++){pq.offer(new int[]{0,i});}while(k>1){int[] vals = pq.poll();if(vals[0]+1 < vals[1]){pq.offer(new int[]{vals[0]+1,vals[1]});}k--;}answer = pq.poll();return new int[]{A[answer[0]],A[answer[1]]};}}

總結

以上是生活随笔為你收集整理的719. Find K-th Smallest Pair Distance的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。