[2022-06-15]719. 找出第 K 小的数对距离👋数组👋双指针👋二分查找👋排序
webVueBlog opened this issue · comments
题目链接: https://leetcode-cn.com/problems/find-k-th-smallest-pair-distance
难度: Hard
标签: 数组 双指针 二分查找 排序
719. 找出第 K 小的数对距离
Description
Difficulty: 困难
Related Topics: 数组, 双指针, 二分查找, 排序
数对 (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
Solution
Language: JavaScript
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var smallestDistancePair = function(nums, k) {
};解答:排序 + 二分查找 + 双指针
给定距离 mid,计算所有距离小于等于mid 的数对数目 cnt 可以使用双指针:初始左端点 i = 0,我们从小到大枚举所有数对的右端点 j,移动左端点直到 nums[j]−nums[i]≤mid,那么右端点为 j 且距离小于等于 mid 的数对数目为 j - i,计算这些数目之和。
var smallestDistancePair = function(nums, k) {
nums.sort((a, b) => a - b);
let n = nums.length, left = 0, right = nums[n - 1] - nums[0];
while (left <= right) {
const mid = Math.floor((left + right) / 2);
let cnt = 0;
for (let i = 0, j = 0; j < n; j++) {
while (nums[j] - nums[i] > mid) {
i++;
}
cnt += j - i;
}
if (cnt >= k) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
}719. 找出第 K 小的数对距离
Description
Difficulty: 困难
Related Topics: 数组, 双指针, 二分查找, 排序
数对 (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
Solution
Language: JavaScript
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var smallestDistancePair = function(nums, k) {
nums.sort((a, b) => a - b);
const n = nums.length;
let left = 0;
let right = nums[n - 1] - nums[0]; // 距离差的范围
while (left < right) {
const mid = (left + right) >>> 1;
if (countLessThenK(mid, k, nums)) left = mid + 1;
else right = mid;
}
return left;
};
const countLessThenK = (mid, k, nums) => {
let [count, start] = [0, 0];
for (let i = 1; i < nums.length; i++) { // start为起点, i 为终点,找出距离差小于mid的数量
while (nums[i] - nums[start] > mid) start++;
count += i - start; // 区间 [start, i] 以内的所有的数的距离差都小于 mid , 所以总数是 i - start
}
return count < k;
}