【Leetcode】719. Find K-th Smallest Pair Distance

题目地址:

https://leetcode.com/problems/find-k-th-smallest-pair-distance/

给定一个长 n n n的数组 A A A,给定不等的两个下标 i i i j j j,我们总能算出数对差 ∣ A [ i ] − A [ j ] ∣ |A[i]-A[j]| A[i]A[j]。给定一个正整数 k k k,问第 k k k小的这样的数对差是多少。下标的顺序不同也视为同一数对。

思路是二分答案。若 A A A的最大值是 M M M,最小值是 m m m,则最大的差显然是 M − m M-m Mm,最小差是 0 0 0。我们可以二分答案,每次二分出一个数 x x x,就看一下比它小于等于的数对差有多少个,如果大于等于 k k k个,则说明最终答案不大于 x x x,则收缩右边界到 x x x;否则说明最终答案大于 x x x,则收缩左边界到 x + 1 x+1 x+1。计算比 x x x小于等于的数对差的个数,可以用排序 + 双指针来做。对数组排好序之后,开两个指针 i i i j j j保持 i > j i>j i>j(因为数对不能取重复数),如果数对差大于 x x x了,则右移左指针,直到数对差小于等于或 j = i j=i j=i为止,然后累加 i − j i-j ij(这里 i − j i-j ij是以 A [ i ] A[i] A[i]为较大值的且数对差小于等于 x x x的数对个数)。注意这里不用回退左指针,原因是回退只会导致数对差更大,得不到答案。代码如下:

import java.util.Arrays;

public class Solution {
    public int smallestDistancePair(int[] nums, int k) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        
        Arrays.sort(nums);
        
        int l = 0, r = nums[nums.length - 1] - nums[0];
        while (l < r) {
            int m = l + (r - l >> 1);
            // 计算一下小于等于m的数对差的个数
            int count = 0;
            for (int i = 0, j = 0; i < nums.length; i++) {
                while (j < i && nums[i] - nums[j] > m) {
                    j++;
                }
                
                count += i - j;
            }
            
            // 如果小于等于m的数对差的个数大于等于k,则收缩右边界,否则收缩左边界
            if (count >= k) {
                r = m;
            } else {
                l = m + 1;
            }
        }
        
        return l;
    }
}

时间复杂度 O ( n ( log ⁡ ( M − m ) + n ) ) O(n(\log (M-m) + n)) O(n(log(Mm)+n)) M M M是数组最大值, m m m是数组最小值,空间 O ( 1 ) O(1) O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值