持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
题目详情
LeetCode题库序号 719. 找出第 K 小的数对距离 ,难度为 困难。
Tag : 「排序」,「二分查找」
数对 (a,b) 由整数 a 和 b 组成,其数对距离定义为 a 和 b 的绝对差值。
给你一个整数数组 nums 和一个整数 k ,数对由 nums[i] 和 nums[j] 组成且满足 0 <= i < j < nums.length 。返回 所有数对距离中 第 k 小的数对距离。
示例 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
提示:
n == nums.length
2 <= n <= 104
0 <= nums[i] <= 106
1 <= k <= n * (n - 1) / 2
进行模拟
题解思路:
- 因为要解答第k小的数对距离,数对距离根据两数对差值的平方差得出,那么由此我们可以得出最小的距离肯定是0,最大的数对距离则是最大值减去最小值
max(nums) - min(nums)
。由此我们知道了距离区间 - 距离区间内查找那个距离值是符合第k小的,可以使用二分查找确定距离值,看下当前选中的距离值的小于该距离值数量的数对数量是否满足k的值,如果满足的话,则表示找到结果,如果不满足,根据数量的大小,进行查找区间的缩小
- 给定距离值判断小于该距离值的数量也可以使用二分查找的方式。通过查找的数量可以得出。统计数量
- 最后比较数对数量。即可得到接口
题解代码
class Solution {
public int smallestDistancePair(int[] nums, int k) {
Arrays.sort(nums);
// 确定距离值区间
int n = nums.length, left = 0, right = nums[n - 1] - nums[0];
while (left <= right) {
int mid = (left + right) / 2;
int cnt = 0;
for (int j = 0; j < n; j++) {
int i = binarySearch(nums, j, nums[j] - mid);
cnt += j - i;
}
if (cnt >= k) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
}
// 查找小于距离值的数量
public int binarySearch(int[] nums, int end, int target) {
int left = 0, right = end;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
结尾
我的"刷完LeetCode题库"系列文章的第 No.719
序号的题目,本次刷题之旅系列开始于 2022-06-12,因为LeetCode上部分是有锁题,我自己的目标是将先把所有不带锁的题目刷完。自己能够通过这次刷题之旅勉励自己,并且提升逻辑思维能力。这个系列的文章就是会见证我自己的一个成长过程!
思路虽然不是最优的,但是我会尽我所能!
为了让我自己的刷题之旅不中断,我特地建立了相关的仓库,来记录我自己的刷题之旅。 github.com/jackpan123/… 。