658. Find K Closest Elements
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:
- The value k is positive and will always be smaller than the length of the sorted array.
- Length of the given array is positive and will not exceed 104
- 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 = 0, right = arr.length - 1; 4 5 int remaining = arr.length - k; 6 while(remaining >= 1) { 7 if (Math.abs(x - arr[left]) > Math.abs(arr[right] - x)) { 8 left++; 9 } else { 10 right--; 11 } 12 remaining--; 13 } 14 List<Integer> list = new ArrayList<>(); 15 for (int i = left; i <= right; 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 (left >= arr.length) return right; 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 }