贪心总结

贪心专题

  贪心(Greedy)的问题我接触不多,它的基本思想很像是在递进状态的时候,采取最有利的方向。比如找零问题,有[1,2,5]面额的硬币,找16块钱,贪心的策略就是用最大的面额整除,余数用比当前小的面额继续整除,最后就得到硬币的数量,这里是5*3+1,4枚硬币。

  与动态规划相比,动态规划类似于在f(n-1)到f(n)的过程中,保持f(n-1)是众多子结构中最优的;而贪心则是只选择当前最优的决策,这样导致可能不是全局最优的选择。

  需要使用贪心决策的地方,需要证明在这种决策下能达到全局最优,当然这个证明我是不会,都是靠经验判断。

55. Jump Game

 

  这个问题的意思是,从起点开始,每个位置表示你能跳的最大位置 。需要计算的是,从起点开始是否能跳到终点。

  这里可以假设你有一个步长范围,每次你到达一个位置的时候,是否能突破你的最大步长,这样遍历到停止就能知道是否到达终点。

  对于n,它取的是当前步长与最大步长相比,如最大者,非常典型的贪心决策。

class Solution {
    public boolean canJump(int[] nums) {
        if(nums == null || nums.length == 0){
            return true;
        }
        int reach = nums[0];
        for(int i=0;i<=reach;i++){
            if(reach<i+nums[i])
                reach = i+nums[i];
            if(reach >= nums.length-1)
                return true;
        }
        return false;
    }

}

  

45. Jump Game II

 

   这个问题是上个问题的基础上,再进了一步。就是要求算出从起点跳用最少的步骤达到终点。

   它的思路,就是在第一问的基础上做一个决策。我们为什么要扩大区间,扩大区间意思是一次能跳的最大步长,那每次都用最大步长去跳就是所求了。变相来说,就是区间扩大的时候,就算是一步。

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

        int reach = 0;
        int max = 0;
        int times = 0;
        for(int i=0;i<=reach;i++){
            if(i+nums[i] > max){
                max = i + nums[i];
            }
            if(i == reach){
                reach = max;
                times ++;
                if(reach >= nums.length-1)
                    break;
            }
        }
        return reach >= nums.length-1?times:0;
    }
}

 12. Integer to Roman

 

   将十进制数转化为罗马数字。

   使用贪心决策,先转化最大的单位,然后逐个降低单位。

class Solution {
    public String intToRoman(int num) {
        StringBuilder str = new StringBuilder();
        String symbol[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        int value[]=    {1000,900,500,400, 100, 90,  50, 40,  10, 9,   5,  4,   1};
        for(int i=0;num!=0;++i)
        {
            while(num>=value[i])
            {
                num-=value[i];
                str.append(symbol[i]);
            }
        }
        return str.toString();
    }
}

11. Container With Most Water

 

   小的那端往中间移动,保证大的端。

class Solution {
    public int maxArea(int[] height) {
        int maxarea = 0, l = 0, r = height.length - 1;
        while (l < r) {
            maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l));
            if (height[l] < height[r])
                l++;
            else
                r--;
        }
        return maxarea;
    }
}

 

posted @ 2019-10-17 14:19  天目山电鳗  阅读(286)  评论(0编辑  收藏  举报