「这是我参与2022首次更文挑战的第33天,活动详情查看:2022首次更文挑战」
题目
给定一个 排序好 的数组 ,两个整数 和 ,从数组中找到最靠近 (两数之差最小)的 个数。返回的结果必须要是按升序排好的。
整数 比整数 更接近 需要满足:
- 或者
- 且
示例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]
复制代码
提示
- 按 升序 排列
题解
双指针
从数组左右两端向中间查找 个目标元素;
- 表示数组左侧指针
- 表示数组左侧指针
- 如果 ;右指针向左移动一步
- 否则左指针向右移动一步。
返回数组 区间数据即可
var findClosestElements = function (arr, k, x) {
const len = arr.length
if (len === 1) return arr
if (k === len) return arr
let left = 0
let right = len - 1
while (right - left >= k) {
const l = arr[left]
const r = arr[right]
if (Math.abs(l - x) <= Math.abs(r - x)) {
right--
} else {
left++
}
}
return arr.slice(left, right + 1)
}
复制代码
二分法
双指针有点慢,有更快的方法吗??二分
分析有序数组减去固定值x的绝对值,新数组排序可以归纳为下图中两种可能;
这就可以转换为找出数组中k个小元素,并且左侧元素优先
核心是
- 如果 最小的 k 个是落在 区间
- 否则 最小的 个是落在 区间
- 最后返回的不是 ,而是
根据上述思路编辑代码如下
var findClosestElements = function (arr, k, x) {
const len = arr.length
let left = 0
let right = len - k
while (left < right) {
const mid = left + ((right - left) >> 1)
if (x - arr[mid] > arr[mid + k] - x) {
left = mid + 1
} else {
right = mid
}
}
return arr.slice(left, left + k)
}
复制代码
结语
作者水平有限,如有不足欢迎指正;任何意见和建议欢迎评论区浏览讨论