719. 找出第 K 小的数对距离
作者:互联网
数对 (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
这道题其实有那么一点二分猜答案的意思,也有很多类似题目,只不过这道题确实表达的不是很清晰不容易想到,题没问题,我的问题。
既然是猜答案,那么二分边界自然就是距离最大值和距离最小值了,每次我们得到一个mid,**遍历数组(双指针或二分)**找到所有小于等于mid的数对数量cnt。
遍历完之后如果cnt小于我们需要的k值,说明距离小了点,需要让左边界右移,这里其实也很好理解的。
就想清楚一个问题,距离越大,那么包含的数对就越多,距离越小当然就越少了,当前mid距离包含的数对cnt小于k,也就是说我们需要更多的cnt,那就增大距离呗,反之亦然。
双指针过程就是经典的一个指针一直右移另一个指针满足条件后直接瞬移,具体实现看代码。
总体来说,题目不难,想到思路比较难。
顺便复习一下快排。
class Solution { public int smallestDistancePair(int[] nums, int k) { mysort(nums); int n = nums.length; int left = 0; int right = nums[n - 1] - nums[0]; int res = 0; while (left <= right) { int mid = left + ((right - left) >> 1); int cnt = 0; for (int i = 0, j = 0; j < n; j++) { while (nums[j] - nums[i] > mid) i++; cnt += j - i; } if (cnt >= k) { res = mid; right = mid - 1; }else { left = mid + 1; } } return res; } public void mysort(int[] nums, int left, int right) { if (left > right) { return; } int key = nums[left]; int i = left; int j = right; while (i < j) { while (i < j && nums[j] >= key) j--; while (i < j && nums[i] <= key) i++; int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } nums[left] = nums[i]; nums[i] = key; mysort(nums, left, i - 1); mysort(nums, i + 1, right); } }
原文:https://leetcode.cn/problems/find-k-th-smallest-pair-distance/solution/by-nice-hermann9a2-jyk5/
标签:找出,719,nums,int,cnt,距离,mid,left 来源: https://www.cnblogs.com/liangren-na/p/16437645.html