round1/day9补/贪心2

1. 关于贪心

还没有悟,什么情况下可以判断我在做局部的最优解?
什么是局部最优?
什么是整体最优?
证明局部最优可以导向整体最优吗?

2. 例题

lc12 整数转罗马数字

本题用了JavaScript

思路

  • 从最大的值(1000)开始减num,同时加进roman字符串里,直到num小于1000为止,则开始匹配下一个合适的数字,如500等。把所有的组合情况都写进来,一共13种,从大到小匹配是否要+
  • tips:特殊情况如4和9的出现,也全部并入可能性,而不是额外再写条件

代码实现

var intToRoman = function(num) {
    let result = "";
    let romanArr = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
    let numberArr = [1000,900,500,400,100,90,50,40,10,9,5,4,1];

    let cursor=0;
    while(cursor<13){
        while(num>=numberArr[cursor]){
            result+=romanArr[cursor];
            num-=numberArr[cursor];
        }
        cursor++;
    }
    return result;
};

lc122 买卖股票最佳时机

思路

//前提:我知道每天的股票价格,我只需要计算总利润,而不用标记是那天买入哪天卖出
局部最优:每天都赚钱,不亏钱–>总体最优:只操作赚钱的天数。即若 next>cur则cur买入prev卖出,若一直不存在则不操作

易错点

注意不要写错prev指针移动的可能性——无论昨天执行什么操作,它都要移动

代码实现

class Solution {
    public int maxProfit(int[] prices) {
        int prev=prices[0];
        int profit=0;

        if(prices == null || prices.length==1){
            return 0;
        }

        for(int i=1;i<prices.length;i++){
            if(prices[i]>prev){
                profit=profit+prices[i]-prev;
            }
            prev=prices[i]; //移动比价接下来的两天
            
        }
        return profit;
    }
}
};

lc55 跳跃游戏I

思路

不熟练
理解题意:前提:不存在跳过界,只有跳不够的情况,即只有nums[i]=0才会断掉
思路:思考num[i]所覆盖的元素里,它们最大能够覆盖到的范围为何,遍历被num[i]囊括的元素并找出最大的覆盖范围

易错点

遍历nums[i]的覆盖范围,从中找出最大的覆盖范围时,注意判断maxrange是否超出总长的条件是if(maxrange>=nums.length-1),不要漏掉-1,因为当我们说覆盖范围,并不包括出发点本身的长度

代码实现

class Solution {
    public boolean canJump(int[] nums) {
        int maxrange=0;
        if(nums.length==1){
            return true;
        }
        
		//遍历nums[i]的覆盖范围,在里面找最大的覆盖范围
        for(int i=0;i<=maxrange;i++){ 
            if(maxrange < i+nums[i]){ //注意为什么是i+nums[i]:因为在遍历覆盖范围里,是从nums[i]自己出发,遍历它和它的长度的,即遍历会到nums[nums[0]]为止
                maxrange=nums[i]+i;
            }
            if(maxrange>=nums.length-1){  //记得算上第一位的长度
                return true;
            }
        }
        return false;
       
    }  
}

lc45 跳跃游戏II

思路

不熟???,待巩固

  1. 什么情况下停止跳跃?当前点就在尽头
  2. 什么情况下需要跳?
    1. 当前点的最大覆盖范围内有下一个点,该点可以覆盖到尽头,再跳一步停止跳跃
    2. 当前点的最大覆盖范围内有下一个最远点,该点无法覆盖到尽头,跳完这步还有下一步

因此需要:

  1. 一个记录当前节点最大覆盖范围,在跳到边界仍然无法覆盖到尽头的时候启动下一步操作
  2. 一个记录该覆盖范围内是否存在最大覆盖范围点,可以跳到尽头

代码实现

class Solution {
    public int jump(int[] nums) {
        if(nums.length==1){
            return 0;
        }

        int maxrange = 0;
        int curmaxrange = 0;
        int count =0;
        
        for(int i=0;i<nums.length;i++){ 
            //在当前节点可覆盖范围中,更新最大覆盖范围 
            maxrange=Math.max(maxrange,nums[i]+i);

            if(maxrange>=nums.length-1){  //如果最大覆盖范围覆盖了终点
                count++; //要再跳一步以到覆盖区域内的终点
                break;
            }
            //如果走到nums[i]当前节点最大范围的尽头,仍够不到终点,无论如何要跳一步
            if(i==curmaxrange){
                curmaxrange=maxrange; //更新最新的最大范围
                count++;
            }
        }


        return count;
    }  
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值