一道美团笔试题

1 篇文章 0 订阅
1 篇文章 0 订阅

给你一个序列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;
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值