问题链接
719. 找出第 K 小的数对距离
问题描述
数对 (a,b)
由整数 a
和 b
组成,其数对距离定义为 a
和 b
的绝对差值。
给你一个整数数组 nums
和一个整数 k
,数对由 nums[i]
和 nums[j]
组成且满足 0 <= i < j < nums.length
。返回 所有数对距离中 第 k
小的数对距离。
提示:
- n == nums.length
- 2 <= n <= 104
- 0 <= nums[i] <= 106
- 1 <= k <= n * (n - 1) / 2
示例
示例1
输入:nums = [1,3,1], k = 1
输出:0
解释:数对和对应的距离如下:
(1,3) -> 2
(1,1) -> 0
(3,1) -> 2
距离第 1 小的数对是 (1,1) ,距离为 0 。
示例2
输入:nums = [1,1,1], k = 2
输出:0
示例3
输入:nums = [1,6,1], k = 3
输出:5
解题思路
看一下提示的范围,就知道暴力破解直接没戏~
这道题,可以对数对距离的域值进行二分查找解题。
- 先对数组
nums
排序; - 对数对距离的域值进行二分查找:
A. 初始left
为0,right
为数组头尾相减的绝对值,middle
为left
与right
和的一半;
B. 统计所有距离小于等于middle
的数对数量,记为count
;
C. 如果count
大于等于k
,right = middle - 1
;反之,left = middle + 1
;
D. 如果left
小于等于right
,继续以上操作; - 当
left
大于right
时,返回结果left
。
代码示例(JAVA)
class Solution {
public int smallestDistancePair(int[] nums, int k) {
// 先进行排序
Arrays.sort(nums);
// 值域二分找k
int length = nums.length;
int left = 0, right = nums[length - 1] - nums[0];
while (left <= right) {
int middle = (right + left) / 2;
int count = countPair(nums, middle);
if (count >= k) {
right = middle - 1 ;
} else {
left = middle + 1;
}
}
return left;
}
// 统计数对
public int countPair(int[] nums, int value) {
int count = 0;
for (int i = 0; i < nums.length - 1; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] - nums[i] <= value) {
count++;
} else {
break;
}
}
}
return count;
}
}
执行结果
网友评论