【leetcode】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
UPDATE (2017/9/19):
The arr parameter had been changed to an array of integers (instead of a list of integers). Please reload the code definition to get the latest changes.

思路

这道题使用的方法是二分查找。
根据题意,首先应该明确的是x不一定在这个数组中,所以不能通过在数组中找到这个数然后进行前后遍历来解决这个问题。其次,这道题中给出的数组是递增的,要求结果也递增。那么,我们可以知道求出的结果一定是原数组的一个子集,只要求出这个子集的开始位置和结束位置,就可以求出答案了。

原题明确,如果有两个数与x的距离相等,就取较小的那个数。所以,我们需要从数组的左边开始遍历。防止溢出,右边的right边界初始化为arrSize-k。
为了清楚地理解这个过程,可以把这个递增的数组比作一个山坡,

A是坡底,C是坡顶,BC段是预留地(也要遍历,初始化arrSize-k只是为了防止right增加时溢出)。从坡底开始向上选择一段符合条件的区域。按照要求,x的大致位置应该处于这段区域的中心位置,这样才能保证这段区域的每个节点(数组中的数)距离x的位置的和是最小的。记录一下这段区域的起点和终点,就可以得出答案了。

代码

int* findClosestElements(int *arr,int arrSize,int k,int x,int* returnSize){
    *returnSize = k;
    int left = 0,right = arrSize - k;
    while(left < right){
        int mid = left + (right - left) / 2;
        if(x - arr[mid] > arr[mid+k] - x)left = mid + 1;
        else right = mid;
    }
    int i;
    int *nums = (int*)malloc(sizeof(int)*(*returnSize));
    for(i = 0; i < k; i++)
        nums[i] = arr[left+ i];
        return nums;
}

参考:

https://www.cnblogs.com/grandyang/p/7519466.html

猜你喜欢

转载自www.cnblogs.com/zhaijiayu/p/9634885.html