Find K Closest Elements

本文介绍了一种高效算法,用于在已排序的数组中找到k个最接近给定数值x的元素,并将结果按升序排列。通过两种方法实现:一种适用于数组长度接近k的情况,另一种则适用于数组长度远大于k的情形。算法详细解释了如何从数组两端逐步逼近目标元素,以确保找到的k个元素与x的距离最小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a sorted array, two integers k and x, find the k closest elements to x in the array. The result should also be sorted in ascending order. If there is a tie, the smaller elements are always preferred.

Example 1:

Input: [1,2,3,4,5], k=4, x=3
Output: [1,2,3,4]

Example 2:

Input: [1,2,3,4,5], k=4, x=-1
Output: [1,2,3,4]

Note:

  1. The value k is positive and will always be smaller than the length of the sorted array.
  2. Length of the given array is positive and will not exceed 104
  3. Absolute value of elements in the array and x will not exceed 104

分析:

这题有两种解法,用于解决不同情况的问题:

1. 如果array 长度和 k 非常接近, 我们可以从array的最左边或者最右边移除 array.length - k个值就可以了。

2. 如果array长度远远大于k,我们可以先找到最大的一个数并且比x小的那个数,然后再以那个数开始从左右扩展,直到取到k个数。

方法一:

 1 class Solution {
 2     public List<Integer> findClosestElements(int[] arr, int k, int x) {
 3         int left = -1, right = arr.length;
 4         
 5         int remaining = arr.length - k;
 6         while(remaining >= 1) {
 7             if (Math.abs(x - arr[left + 1]) > Math.abs(arr[right - 1] - x)) {
 8                 left++;
 9             } else {
10                 right--;
11             }
12             remaining--;
13         }
14         List<Integer> list = new ArrayList<>();
15         for (int i = left + 1; i <= right - 1; i++) {
16             list.add(arr[i]);
17         }
18         return list;
19     }
20 }

方法二:

 1 class Solution {
 2     public List<Integer> findClosestElements(int[] arr, int k, int x) {
 3         int closest = closest(arr, x);
 4         int left = closest;
 5         int right = closest;
 6         while (k > 1) {
 7             if (Math.abs(x - getValue(arr, left - 1)) <= Math.abs(x - getValue(arr, right + 1))) {
 8                 left--;
 9             } else {
10                 right++;
11             }
12             k--;
13         }
14         
15         List<Integer> list = new ArrayList<>();
16         for (int i = left; i <= right; i++) {
17             list.add(arr[i]);
18         }
19         return list;
20     }
21     
22     private int closest(int[] arr, int x) {
23         int left = 0, right = arr.length - 1;
24         while (left <= right) {
25             int mid = left + (right - left) / 2;
26             if (arr[mid] == x) {
27                 return mid;
28             } else if (arr[mid] < x) {
29                 left = mid + 1;
30             } else {
31                 right = mid - 1;
32             }
33         }
34         if (right < 0) return left;
35         if (right >= arr.length) return left;
36         return Math.abs(x - arr[left]) > Math.abs(x - arr[right]) ? right : left;
37     }
38     
39     private long getValue(int[] arr, int idx) {
40         if (idx < 0) return Integer.MIN_VALUE;
41         if (idx >= arr.length) return Integer.MAX_VALUE;
42         return arr[idx];
43     }
44 }

 

转载于:https://www.cnblogs.com/beiyeqingteng/p/10398979.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值