博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
658. Find K Closest Elements - Medium
阅读量:6073 次
发布时间:2019-06-20

本文共 3231 字,大约阅读时间需要 10 分钟。

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=3Output: [1,2,3,4]

 

Example 2:

Input: [1,2,3,4,5], k=4, x=-1Output: [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

 

M1: 找出k个最近的元素 <==> 在原数组中删除n-k个最远的元素

因为数组有序,离x最远的元素肯定在首、尾出现。先把arr元素复制到新的res arraylist里,每次比较首、尾元素与x之差。如果末尾元素与x之差更大,就去掉末尾元素;如果首元素与x之差更大,就去掉首元素。循环结束条件是res的大小 <= k.

时间:O(N),空间:O(1)

class Solution {    public List
findClosestElements(int[] arr, int k, int x) { List
res = new ArrayList<>(); for(int i = 0; i < arr.length; i++) { res.add(arr[i]); } if(arr == null || arr.length == 0) return res; while(res.size() > k) { if((x - res.get(0)) <= (res.get(res.size() - 1) - x)) res.remove(res.get(res.size() - 1)); else res.remove(res.get(0)); } return res; }}

 

 

M2: 改进,用binary search(上面的方法太慢了)

定义一个区间,l = 0, r = arr.length - k,每次比较 中点m所在元素与x之差 和 m+k所在元素与x之差,如果 中点m所在元素与x之差 更大,说明m右侧的元素与x之差更小,l = m+1;反之如果 m+k所在元素与x之差 更大,说明m左侧的元素与x之差更小,r = m。最后的l就是所求区间的左边界,返回区间[l, l+k)

时间:O(logN),空间:O(1)

class Solution {    public List
findClosestElements(int[] arr, int k, int x) { List
res = new ArrayList<>(); if(arr == null || arr.length == 0) return res; int l = 0, r = arr.length - k; while(l < r) { int m = l + (r - l) / 2; if((x - arr[m]) > (arr[m+k] - x)) l = m + 1; else r = m; } for(int i = l; i < l + k; i++) { res.add(arr[i]); } return res; }}

 

二刷:

首先用binary search找到 <= target 的最大元素,其下标作为left, right = left + 1

然后从中间往两边找,left, right两个指针,谁小(和target之差小)移谁

time: O(log(n) + k), space: O(1)

class Solution {    public List
findClosestElements(int[] arr, int k, int x) { int left = 0, right = arr.length - 1; while(left + 1 < right) { int mid = left + (right - left) / 2; if(arr[mid] == x) left = mid; else if(arr[mid] > x) right = mid; else left = mid; } int tmp; if(arr[right] <= x) tmp = right; if(arr[left] <= x) tmp = left; else tmp = -1; left = tmp; right = left + 1; List
res = new ArrayList<>(); for(int i = 0; i < k; i++) { if(left >= 0 && right <= arr.length - 1 && Math.abs(arr[left] - x) <= Math.abs(arr[right] - x)) left--; else if(left >= 0 && right > arr.length - 1) left--; else right++; } for(int i = left + 1; i < right; i++) { res.add(arr[i]); } return res; }}

 

转载于:https://www.cnblogs.com/fatttcat/p/10062228.html

你可能感兴趣的文章
环境变量
查看>>
Swift 项目中可能用到的第三方框架
查看>>
我的友情链接
查看>>
普通exe和sys驱动文件结构上有什么不同?
查看>>
Shell脚本查看apk签名信息
查看>>
raid数据恢复,Raid5磁盘阵列数据恢复案例,服务器数据恢复
查看>>
Active Directory授权还原
查看>>
双因素方差分析
查看>>
Skype for Business Server 2015 后端数据库配置镜像见证(mirroring witness)
查看>>
Exchange Server 2013安装(为和Lync Server 2013集成做准备)
查看>>
关于光标属性cursor
查看>>
IIS6.0环境php5.3.6配置
查看>>
智力面试题
查看>>
我的友情链接
查看>>
Web Service 之 http(一)
查看>>
微软认罚不会上诉
查看>>
html学习
查看>>
我的友情链接
查看>>
java对象引用以及对象赋值
查看>>
遍历Map的四种方法
查看>>