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
思路
不熟???,待巩固
- 什么情况下停止跳跃?当前点就在尽头
- 什么情况下需要跳?
- 当前点的最大覆盖范围内有下一个点,该点可以覆盖到尽头,再跳一步停止跳跃
- 当前点的最大覆盖范围内有下一个最远点,该点无法覆盖到尽头,跳完这步还有下一步
因此需要:
- 一个记录当前节点最大覆盖范围,在跳到边界仍然无法覆盖到尽头的时候启动下一步操作
- 一个记录该覆盖范围内是否存在最大覆盖范围点,可以跳到尽头
代码实现
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;
}
}