1. 程式人生 > >leetcode658_找到k個最接近的元素

leetcode658_找到k個最接近的元素

給定一個排序好的陣列,兩個整數 k 和 x,從陣列中找到最靠近 x(兩數之差最小)的 k 個數。返回的結果必須要是按升序排好的。如果有兩個數與 x 的差值一樣,優先選擇數值較小的那個數。

示例 1:

輸入: [1,2,3,4,5], k=4, x=3
輸出: [1,2,3,4]
 

示例 2:

輸入: [1,2,3,4,5], k=4, x=-1
輸出: [1,2,3,4]
 

說明:

k 的值為正數,且總是小於給定排序陣列的長度。
陣列不為空,且長度不超過 10^4
數組裡的每個元素與 x 的絕對值不超過 10^4

 

思路:

由於陣列有序,所以最後找到的k個元素也一定是有序的,其實就是返回了一個長度為k的子陣列,相當於在長度為n的陣列中去掉n-k個數字, 而且去掉的順序肯定是從兩頭開始去,因為距離x最遠的數字肯定在首尾出現。每次比較首尾兩個數字跟x的距離,將距離大的那個數字刪除,直到剩餘的陣列長度為k為止。

//留下最近的  也就是去掉最遠的  直到陣列長度為k
	 public List<Integer> findClosestElements1(int[] arr, int k, int x) {
			 List<Integer> res=new ArrayList<>();
			 int len=arr.length;
			 int left=0;
			 int right=len-1;
			 while (len>k) {
				if (Math.abs(arr[left]-x)>Math.abs(arr[right]-x)) {
					left++;
				}else {
					right--;
				}
				len--;
			}
	        for (int index = left; index <=right; index++) {
	                  res.add(arr[index]);       
			}
		     return res;	        
	    }

 

還可以利用二分的方法  找到距離最近區間的起點

 public List<Integer> findClosestElements(int[] arr, int k, int x) {
	        List<Integer> res = new ArrayList<>();
	        int start = 0, end = arr.length-k;
	        while(start<end){
	            int mid = start + (end-start)/2;
	            if(Math.abs(arr[mid]-x)>Math.abs(arr[mid+k]-x)){ //中位數距離x比較遠  所以看右半部分 
	                start = mid+1;
	            } else {
	                end = mid;
	            }
	        }
	        for(int i=start; i<start+k; i++){
	            res.add(arr[i]);
	        }
	        return res;
	    }