658. 找到 K 个最接近的元素
原始题目链接:https://leetcode.cn/problems/find-k-closest-elements/
给定一个 排序好 的数组 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]
解题思路:
因为数组有序,题目要求最靠近x的k个值,可以使用两个指针,一头一尾,不断计算和x的差值,排除掉较大的元素,最后保留k个即可。
代码实现:
class Solution:
def findClosestElements(self, arr: List[int], k: int, x: int) -> List[int]:
arr_len = len(arr)
left = 0
right = arr_len - 1
# 最终保留k个,所以一共需要删除的元素个数是arr_len - k
del_size = arr_len - k
for i in range(del_size):
# 右边的元素和x的差值比左边的元素和x的差值大
# 删除大的元素,因为越大的越不靠近x
if x - arr[left] <= arr[right] - x:
right -= 1
else:
left += 1
i += 1
return arr[left: right + 1]
方法2:
数组有序,想到二分法,在一个包含k+1个元素的连续区间上删除不符合的元素。
class Solution:
def findClosestElements(self, arr: List[int], k: int, x: int) -> List[int]:
size = len(arr)
left = 0
right = size - k
# 在一个包括 k + 1个元素的区间排除不符合的元素
# 所以左右边界点初始化为0和size-k
while left < right:
mid = left + (right - left) // 2
if x - arr[mid] <= arr[mid + k] - x:
right = mid
else:
left = mid + 1
return arr[left : left + k]
参考文献:
https://leetcode.cn/problems/find-k-closest-elements/solution/pai-chu-fa-shuang-zhi-zhen-er-fen-fa-python-dai-ma/