LeetCode 找出第k小的距离对(二分搜索)

给定一个整数数组,返回所有数对之间的第 k 个最小距离。一对 (A, B) 的距离被定义为 A 和 B 之间的绝对差值。

示例 1:

输入:
nums = [1,3,1]
k = 1
输出:0 
解释:
所有数对如下:
(1,3) -> 2
(1,1) -> 0
(3,1) -> 2
因此第 1 个最小距离的数对是 (1,1),它们之间的距离为 0。

提示:

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

思路分析: 与 LeetCode 乘法表中第k小的数(二分搜索) 非常类似。
最大的距离必定是最大值 - 最小值,而最小的距离可能是0(也可能比0大)。所以我们采用二分法,初始化left = 0, right = 最大距离。对于mid = (left + right) / 2,我们计算距离小于等于k个距离对的个数shortDisMid。

如果shortDisMid < k, 则第k小的距离对必定不会出现在[left, mid],所以修改left = mid + 1
否则 right = mid
class Solution {
public:
	int smallestDistancePair(vector<int>& nums, int k) {
		sort(nums.begin(), nums.end());//按照升序排序
        //二分搜索的三个指针,left初始化为0,right初始化为最大的距离
		int left = 0, right = nums.back() - nums[0], mid;
		while (left < right) {
			mid = (left + right) / 2;
			int shortDisMid = findDistaceShort(nums, mid);//获取距离大小不超过k的距离对的个数
            //缩小[left, right]区间
			if (shortDisMid < k) {
                //<= mid的距离对个数小于k,则第k小的距离必定不会出现在[left, mid]
				left = mid + 1;
			}
			else {
				right = mid;
			}
		}
		return left;
	}
    //寻找距离不超过distance的个数(nums已经按照升序排序)
	int findDistaceShort(vector<int>& nums, int distance) {
        //rightIndex代表的是在index左边且与nums[index]的距离不超过distanc的下标
		int numsSize = nums.size(), res = 0, rightIndex = numsSize - 1;
		for (int index = numsSize - 2; index >= 0; --index) {
            //修正index左边与与nums[index]的距离不超过distanc的下标
			while (rightIndex > index && nums[rightIndex] - nums[index] > distance) {
				--rightIndex;
			}
			res += (rightIndex - index);//则以index为一端,距离不超过distance的个数就是rightIndex - index
		}
		return res;
	}
};

LeetCode 找出第k小的距离对(二分搜索)_第1张图片

你可能感兴趣的:(LeetCode,二分法,数组)