20220825每日一题:力扣658.找到k个最接近的元素

题目

给定一个 排序好 的数组 arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。

整数 a 比整数 b 更接近 x 需要满足:

  • |a - x| < |b - x| 或者
  • |a - x| == |b - x|且a < b

示例

输入:arr = [1,2,3,4,5], k = 4, x = 3
输出:[1,2,3,4]

输入:arr = [1,2,3,4,5], k = 4, x = -1
输出:[1,2,3,4]

解法一:滑动窗口

由于题目中数组是已经排序好的,因此最靠近x的数应该是分布在x两侧的连续k个数。返回结果为固定长度窗口,因此可以考虑滑动窗口解法,具体步骤如下:

  • **Step1:**初始化一个长度为k的窗口;
  • **Step2:**滑动窗口,计算x与左右边界的距离dist。若 distLeft > distRight或窗口内数据值相同,窗口右移,否则,跳出循环;
  • **Step3:**返回左右边界内所有数据为所求

具体实现思路如下:

class Solution {

    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        
        // 初始化滑动窗口
        int size = arr.length;
        int left = 0,right = k - 1;

        while(right + 1 < size){
        	// 若窗口内数据相同,右移
            if(arr[right + 1] == arr[left]){
                ++right;
                ++left;
                continue;
            }
            // 若distLeft > distRight,右移
            if(Math.abs(arr[right + 1] - x) < Math.abs(arr[left] - x)){
                ++right;
                ++left;
                continue;
            }
            break;
        }

		// 返回左右边界内数据
        List<Integer> ans = new ArrayList<>();
        for(int i = left; i <= right; ++i){
            ans.add(arr[i]);
        }

        return ans;

    }


}

其运行结果如下:

执行用时:4 ms, 在所有 Java 提交中击败了73.23%的用户
内存消耗:43.6 MB, 在所有 Java 提交中击败了27.85%的用户

解法二:双指针

由于答案一定为连续的数组,因此可以采用双指针的方式,从数组两端向中间逼近,确定最终数组位置。

其实现逻辑如下:

class Solution {

    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        
        List<Integer> ans = new ArrayList<>();
				// 初始化左右指针和需要移除的元素数量
        int left = 0,right = arr.length - 1,removeSize = arr.length - k;

				// 当移除数量大于0(即当前窗口大于k),继续逼近
        while(removeSize > 0){
        		// 边界逼近,当相同时优先缩小右边界
            if(Math.abs(arr[left] - x) > Math.abs(arr[right] - x)){
                ++left;
                --removeSize;
                continue;
            }
            if(Math.abs(arr[left] - x) <= Math.abs(arr[right] - x)){
                --right;
                --removeSize;
                continue;
            }
        }

        for(int i = left; i <= right; ++i){
            ans.add(arr[i]);
        }

        return ans;

    }


}

其运行结果如下:

执行用时:4 ms, 在所有 Java 提交中击败了73.23%的用户
内存消耗:43.2 MB, 在所有 Java 提交中击败了67.11%的用户
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目描述: 给你两个版本号 version1 和 version2 ,请你比较它们。 版本号由一个或多个修订号组成,各修订号由一个 '.' 连接。每个修订号由多位数字组成,可能包含前导零。每个版本号至少包含一个字符。修订号从左到右编号,下标从0开始,最左边的修订号下标为0 ,下一个修订号下标为1,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。 比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较忽略任何前导零后的整数值。也就是说,修订号1和修订号001相等。如果版本号没有指定某个下标处的修订号,则该修订号视为0。例如,版本1.0 小于版本1.1,因为它们下标为0的修订号相同,而下标为1的修订号分别为0和1,0 < 1。 返回规则如下: 如果 version1 > version2 返回 1, 如果 version1 < version2 返回 -1, 否则返回 0。 示例 1: 输入:version1 = "1.01", version2 = "1.001" 输出:0 解释:忽略前导零,"01" 和 "001" 都表示相同的整数 "1" 示例 2: 输入:version1 = "1.0", version2 = "1.0.0" 输出:0 解释:version1 没有指定下标为 2 的修订号,即视为 "0" 示例 3: 输入:version1 = "0.1", version2 = "1.1" 输出:-1 解释:version1 中下标为 0 的修订号是 0,version2 中下标为 0 的修订号是 1 。0 < 1,所以 version1 < version2 示例 4: 输入:version1 = "1.0.1", version2 = "1" 输出:1 示例 5: 输入:version1 = "7.5.2.4", version2 = "7.5.3" 输出:-1 提示: 1 <= version1.length, version2.length <= 500 version1 和 version2 仅包含数字和 '.' version1 和 version2 都是 有效版本号

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值