330. 按要求补齐数组(Java)

330. 按要求补齐数组(😦😦😦😦😦😦😦😦)

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

在这里插入图片描述
思路:贪心算法
找到当前数据(原有的+新加入的)所能覆盖的最大连续范围

一个数组[a1,a2,a3…an]当前能用和表示的数字区间为[1,right],此时往数组内补充新数num,则此时能表示的区间为[1,right]∪[num,right + num]
首先由于num被添加进了数组,则能实现的最大的数显然变成了right + num,而由于right之前的数[1, right]都可以实现,那么,实现[0+num,…,j+num,…right + num]就可以用 j+ num实现

本题的贪心思想即来源于此,为了使补充的新数物尽其用,能够直接扩大可表示的区间范围,把补充的num设为right + 1即可。此时能表示的数字区间可以直接更新为[1, ach + ach + 1],不会漏掉中间的数字。

所以本题的思路是这样的:

1.当前能表示的最大数字为right,则下一个需要达到的目标数字是right + 1,而当前(未使用)的数组元素为num = nums[index]
判断num与目标值right + 1的大小关系,
2.如果num > right + 1,则说明[right + 1, num - 1]区间内的数字无法表示,必须补充插入新数。为了使插入的新数既能表示right + 1,又能尽可能覆盖更多的数组(贪心的关键之处),插入的数字就是right + 1,更新right = right + right + 1
3.如果num < right + 1,说明当前的目标值right + 1可以通过num及其之前的数实现(因为num >= 1),此时更新right = right + num【即不需要额外添加元素就可以扩大连续最大覆盖范围】

class Solution {
    public int minPatches(int[] nums, int n) {
		//贪心算法:找到当前可覆盖的最大连续区间,用right表示当前能覆盖的连续范围的最大值
		//使用int对于测试集可能会溢出
        long right=0;//初始:能覆盖的最大连续范围为0
		int count=0;//记录需要添加的元素的个数
		int index=0;//记录nums的下标
		while (right<n) {
            //所覆盖的范围一定比i先到达n
			if (index>=nums.length || right+1 < nums[index]) {
				//当前能表示的最大数字为right,则下一个需要达到的目标数字是right + 1,而当前(未使用)的数组元素为num = nums[idx]
                //如果right与nums[index]之间差的比1多,则需要插入新的元素
				count++;
				right+=right+1;
			}
			else {
				//不需要添加元素就可以扩大覆盖范围
				right += nums[index];
                index++;
				}
		}
		return count;
		

    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值