标签:被锁 不用 pre back tor not i++ 二分 nat
问题:
求给定数组中两两元素之差,从小到大第k个差是多少
Example 1: Input: nums = [1,3,1] k = 1 Output: 0 Explanation: Here are all the pairs: (1,3) -> 2 (1,1) -> 0 (3,1) -> 2 Then the 1st smallest distance pair is (1,1), and its distance is 0. Note: 2 <= len(nums) <= 10000. 0 <= nums[i] < 1000000. 1 <= k <= len(nums) * (len(nums) - 1) / 2.
解法1:
暴力求解法:
首先排序数组,然后两两遍历元素,求之差存入桶数组,差为桶数组的index,桶数组的value为差为index的pair个数。
然后从0~桶数组size去遍历桶数组,cout+=value累加>=k时,返回index
参考代码:
1 class Solution { 2 public: 3 int smallestDistancePair(vector<int>& nums, int k) { 4 sort(nums.begin(), nums.end()); 5 int bucket[nums.back()+1]; 6 memset(bucket, 0, sizeof(bucket)); 7 int cout=0; 8 for(int i=0; i<nums.size(); i++){ 9 for(int j=i+1; j<nums.size(); j++){ 10 bucket[nums[j]-nums[i]]++; 11 } 12 } 13 for(int i=0; i<nums.back()+1; i++){ 14 cout+=bucket[i]; 15 if(cout>=k) return i; 16 } 17 return 0; 18 } 19 };
解法2:
二分查找,动态规划:
首先sort原数组,
查找要找的第k个差的值m是多少
l=最小差值0,r=最大差值nums.back()-nums[0]
每次计算到该m个差值,一共有多少cout个满足的两两元素对,
若个数cout>=k,那么应在 l~m-1 寻找新的m(第k个小的差)
??这里同时可能为最终的查找结束点,当前m=l=r被锁定,cout>=k,r=m-1使得r<l,退出循环。
若个数cout<k,那么应在 m+1~r 寻找新的m(第k个小的差)
其中,每次计算cout的话,应有以下计算方法:
遍历i:0~n,遍历j:i+1~n,求两个元素nums[i]和nums[j]的差(<=m):
??其中,每次递增 i ,又要重新遍历 j,复杂度太大,
由于每次要求的只是临界,i和j的差值<=m后的cout数(=j-i)
(注意??这里退出循环时j++不满足循环条件,因此满足条件的 j 应该-1,即cout数应该为 j-1-i),
我们每次递增 i 的时候,已经遍历到的 j 和 i 的差值一定是缩小了的,我们只需继续从当前的 j 开始递增,继续去找接下来的 j 就可以了。
参考代码:
1 class Solution { 2 public: 3 int smallestDistancePair(vector<int>& nums, int k) { 4 sort(nums.begin(), nums.end()); 5 int n=nums.size(); 6 int cout=0; 7 int l=0, r=nums.back()-nums[0], m; 8 while(l<=r){ 9 cout=0; 10 m=l+(r-l)/2; 11 int j=1; 12 for(int i=0; i<n; i++){//O(n) j不用重新从头开始遍历 13 while((nums[j]-nums[i]<=m)&&j<n) j++; 14 cout+=(j-1-i); 15 } 16 if(cout>=k){ 17 r=m-1; 18 }else{ 19 l=m+1; 20 } 21 } 22 return l; 23 } 24 };
719. Find K-th Smallest Pair Distance
标签:被锁 不用 pre back tor not i++ 二分 nat
原文地址:https://www.cnblogs.com/habibah-chang/p/12826490.html