Leetcode 719. Find K-th Smallest Pair Distance
Problem:
Given an integer array, return the k-th smallest distance among all the pairs. The distance of a pair (A, B) is defined as the absolute difference between A and B.
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
.
Solution:
这道题和Leetcode 774相比真是有过之而无不及,就算我看了标签是用Binary Search也不知道该如何解决。这道题和774有类似之处,首先这两道题都可以事先确定结果可能的范围,然后在这个范围内进行二分查找,对中间的数作为结果去验证是否满足条件,也是使用了逆向思维。首先对数组进行排序,我们知道第k个小的pair的距离必然在0到数组的极差之间,所以我们在这个范围内进行二分搜索,每次搜索都要计算在全部的pair中距离小于pivot的对数,如果小于pivot的pair数量太小,说明我们的pivot值小于真正的结果值,所以left+1,否则说明pivot过大,将right设置为pivot,在这里计算全部的pair中距离小于pivot的对数时还用了一个滑动窗口,用来在线性时间复杂度内计算小于pivot的pair的对数。因此次时间复杂度为O(nlogn+nlog W),W为极差。
Code:
1 class Solution { 2 public: 3 int smallestDistancePair(vector<int>& nums, int k) { 4 int m = nums.size(); 5 sort(nums.begin(),nums.end()); 6 int left = 0; 7 int right = nums.back()-nums[0]; 8 while(left < right){ 9 int pivot = left+(right-left)/2; 10 int count = 0; 11 int start = 0; 12 for(int i = 0;i != m;++i){ 13 while(start < i && nums[i]-nums[start] > pivot) 14 start++; 15 count += (i-start); 16 } 17 if(count < k) left = pivot+1; 18 else right = pivot; 19 } 20 return left; 21 } 22 };