每日一题:贪心算法解按要求补齐数组

一,问题描述

给定一个已排序的正整数数组nums,和一个正整数n。从[1, n]区间内选取任意个数字 补 充 到 nums 中 , 使 得 [1,n] 区 间 内 的 任 何 数 字 都 可 以 用 nums 中 某 几 个 数 字 的 和 来 表 示。请输出满足上述要求的最少需要补充的数字个数。

实例1:

输入: n u m s=[ 1 , 3 ] , n=6

输出: 1

解释: 根据n u m s里现有的组合[ 1 ] , [ 3 ] , [ 1 , 3 ],可以得出1 , 3 , 4。 现 在 如 果 我 们 将 2 添 加 到 n u m s 中 , 组 合 变 为 : [ 1 ] , [ 2 ] , [ 3 ] , [ 1 , 3 ] , [ 2 , 3 ] , [ 1 , 2 , 3 ]。 其和可以表示数字1 , 2 , 3 , 4 , 5 , 6,能够覆盖[ 1 , 6 ]区间里所有的数。 所以我们最少需要添加一个数字。

实例2:

输入: n u m s=[ 1 , 5 , 1 0 ] , n=2 0

输出: 2

解释:我们需要添加[ 2 , 4 ]。

实例3:

输入: n u m s=[ 1 , 2 , 2 ] , n=5

输出: 0

二,贪心算法解决

由题可知,数组nums是升序序列。

假设数组前k 个数组成的数字范围为[ 1,m],那么加上第k+1 个数 即nums[k]( 数 组 的 下 标 是 从 0 开 始 的 ) 后,这个数字范围就变成:[1,total]U[nums [k],total+nums [k]],一个并集,观察一下我们会发现:

1,如果total+1<nums[k],则中间会有一个空缺,无法变为[1,total+nums[k]].

例如:[1,5]U[7,10],因为5<7-1,所以是没法构成[1,10]的。

此时,我们就要循环添加数字total+1来扩大前面的数字范围,构成更大的范围[1,total*2+1],且直到空缺被填补。

2,如果total+1>=nums[k],则无需再添加数字了。

代码:

int mend(vector<int>& nums, int n)
	{
		//total 是前k个数的总和,count累计添加的数,k 为数组下标
		long total = 0;
	    int count=0,k=0;
		while (total < n)
		{
			if (k<nums.size() && total + 1 < nums[k])
			{
				//如果数组能组成的数字范围是[1,total],那么加上nums[k]
				//结果就是[1,total+nums[k]]
				total += nums[k++];
			}
			else
			{
				//添加一个数,count加一
				total = total + (total + 1);
				count++;
			}
		}
		return count;
	}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别抢我的辣条~

老板大气!祝老板身体健康!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值