网络异常,图片无法展示
|
「这是我参与2022首次更文挑战的第35天,活动详情查看:2022首次更文挑战」
给定一个 排序好 的数组 arr
,两个整数 k
和 x
,从数组中找到最靠近 x
(两数之差最小)的 k
个数。返回的结果必须要是按升序排好的。
整数 a
比整数 b
更接近 x
需要满足:
|a - x| < |b - x|
或者|a - x| == |b - x|
且a < b
示例 1:
输入: arr = [1,2,3,4,5], k = 4, x = 3 输出: [1,2,3,4] 复制代码
示例 2:
输入: arr = [1,2,3,4,5], k = 4, x = -1 输出: [1,2,3,4] 复制代码
提示:
1 <= k <= arr.length
1 <= arr.length <= 104
arr
按 升序 排列-104 <= arr[i], x <= 104
解题思路
本题要求我们找到 k
个最接近目标值的元素,因为元素数量是给定的 k
个,而且输入数组是按升序排列的,所以我们可以初始化一个滑动窗口,长度为 k
,计算窗口中每个元素与目标值 x
的差值和,然后扫描从头到尾移动这个窗口,找到差值和最小的窗口,则窗口中的元素就是我们要找的 k
个数。
因为输入数组是有序的,所以当窗口下一次移动的差值和大于当前窗口的差值和,则后续的窗口范围内的差值和都会大于当前窗口的差值和,所以此时可以停止移动,返回当前窗口中的元素。
又因为根据示例1可知,当两个窗口中元素的差值和相等的时候,优先选择前面的窗口,所以我们需要从数组末尾确定窗口,然后向前移动。
代码实现
var findClosestElements = function(arr, k, x) { // 初始化窗口的左右边界下标 let r = arr.length-1,l = r-k+1, // 初始化窗口内元素和目标值的差值 diff = 0; // 计算窗口内元素和目标值的差值 for(let i = r;i>=l;i--) diff += Math.abs(arr[i]-x) // 当窗口左边界没有到达下标 0 时,向左移动窗口 while(l>0){ // 计算窗口下次移动后的差值和 const nextDiff = diff-Math.abs(arr[r]-x)+Math.abs(arr[l-1]-x) // 如果下次移动后窗口的差值和小于等于当前窗口的差值和 if(nextDiff<=diff){ // 移动窗口 l--; r--; // 更新当前窗口的差值和 diff = nextDiff; } // 否则说明找到了差值和最小的窗口,返回窗口中的元素 else return arr.slice(l,l+k) } // 如果可以一直移动到数组最左侧,则说明最左侧的窗口是差值最小的窗口,返回该窗口中的元素 return arr.slice(l,l+k) } 复制代码
至此我们就完成了 leetcode-658-找到 K 个最接近的元素
如有任何问题或建议,欢迎留言讨论!👏🏻👏🏻👏🏻