给你一个序列nums,问你最少删除几个数,使得这个序列的最大值和最小值相差小于等于k
这道我的想法比较简单,复杂度O(nlogn)是可以解决的
首先给序列排个序,这样序列就是从小到排了,那我们的目标,就是找到一个起点,一个终点,终点的值与起点的值的差小于等于k, 我们希望起点和终点离得尽可能远。
有一个简单的O(n^2)的处理是,序列每一个位置都可以作为起点来尝试,这样有n个起点选择,起点及其后的点,可以作为终点的选择,那每一个点有最多n个终点选择,那一共是n^2个选择。
但其实我们可以优化,比如我们确定起点start后,那我们要找一个终点end,满足 nums[end] - nums[start] <= k, 也就是 nums[end] <= k + nums[start], 我们可以通过二分法,找到这个最大的end。
下面是代码,不过思路不一样,是先确定终点,然后二分法找起点., 找到最小的start满足nums[start] >= nums[end] - k
function countK(nums, k){
let sorted_nums = nums.sort((a,b)=>a-b);
let n = nums.length;
let min = n;
for(var j = n - 1; j >= 0; j--){
let i = binarySearch(sorted_nums, sorted_nums[j] - k, 0, j);
if(i != -1){
min = min < ( n - (j-i+1))?min:(n - (j - i + 1));
}
}
return min;
}
let nums = [1, 2, 9,10, 20, 22, 24, 26, 28]
console.log(countK(nums,0));
//console.log(binarySearch(nums,29,0,nums.length-1));
// find the min index of a num which >= target
function binarySearch(nums, target, s, e){
console.log(target, s, e);
let start = s;
let end = e, mid;
while(start < end){
mid = (start+end) >> 1;
if(target <= nums[mid]){
end = mid;
}else{
start = mid + 1;
}
}
if(nums[start] >= target)
return start;
else
return -1;
}