• 贪心算法(常与栈/队列/堆结合)


    前言

    贪心算法(又称贪婪算法)是指:
    	在对问题求解时,总是做出局部最优解。
    
    
    贪心算法的基本思路:
    
    	根据某个优化测度,每一步都要确保能获得局部最优解。
    	每一步只考虑一个数据,他的选取应该满足局部优化的条件。
    
    	若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完。
    
    
    贪心策略适用的前提是:
    	局部最优策略能导致产生全局最优解。
    

    跳跃游戏

    /**
     * 给定一个非负整数数组,你最初位于数组的第一个位置。
     * 
     * 数组中的每个元素代表你在该位置可以跳跃的最大长度。
     * 
     * 判断你是否能够到达最后一个位置。
     * 
     * 思路:贪心法
     * 		循环数组,如果可以达到的最大位置<当前位置,返回false,标识无法跳跃到最后。
     * 
     * 时间复杂度:O(n)。
     * 空间复杂度:O(1)。
     */
    class Solution1 {
        public boolean canJump(int[] nums) {
            int max = 0;
            for (int i = 0; i < nums.length; i++) {
                if (max < i) return false;	//如果不能跳到当前位置:返回false
                max = Math.max(max, i + nums[i]);	//可以跳到当前位置:当前位置与最大位置相比较,更新可以跳跃的最远位置
            }
            return true;
        }
    }
    
    
    /**
     * 给定一个非负整数数组,你最初位于数组的第一个位置。
     * 
     * 数组中的每个元素代表你在该位置可以跳跃的最大长度。
     * 
     * 你的目标是使用最少的跳跃次数到达数组的最后一个位置。
     * 
     * 示例:
     * 		输入: [2,3,1,1,4]
     * 		输出: 2
     * 
     * 思路:贪心算法
     * 		明确什么时候跳跃最合适:
     * 		每次跳跃(在自己当前的跳跃区间内)保证这次跳跃可以使下次跳跃到更远的位置
     * 
     * 注;如果数组只有一个元素。则只需要跳0次。
     * 
     * 时间复杂度:O(n)。
     * 空间复杂度:O(1)。
     */
    class Solution2 {
        public int jump(int[] nums) {
            int end = 0;  //边界
            int max = 0;  //可以跳的最大值
            int step = 0; //步数
            for (int i = 0; i < nums.length - 1; i++) {
                max = Math.max(max, nums[i] + i);
                if (i == end) {
                    step++;
                    end = max;
                }
            }
            return step;
        }
    }
    

    找出可以组成的最长摆动序列的长度(去掉某些元素)

    /**
     * 摆动序列:贪心法
     */
    class Solution {
        public int wiggleMaxLength(int[] nums) {
            if (nums.length <= 1) return nums.length;
            if (nums.length == 2) return nums[0]-nums[1]==0?1:2;
    
            int len = 1;
            int temp = nums[0];
            int up = 0;
            int down = 0;
    
            for (int i = 1; i < nums.length; i++) {
                if (nums[i] > temp) {
                    if (up == 0) {
                        down = 0;
                        len++;
                    }
                    up++;
                    temp = nums[i];
                } else if(nums[i] < temp){
                    if (down == 0) {
                        up = 0;
                        len++;
                    }
                    down++;
                    temp = nums[i];
                }
            }
            return len;
        }
    }
    
    
    /**
     * 摆动序列:贪心法(大神解法)
     */
    class Solution1 {
        public int wiggleMaxLength(int[] nums) {
            if (nums.length < 2)
                return nums.length;
            int prevdiff = nums[1] - nums[0];
            int count = prevdiff != 0 ? 2 : 1;
            for (int i = 2; i < nums.length; i++) {
                int diff = nums[i] - nums[i - 1];
                if ((diff > 0 && prevdiff <= 0) || (diff < 0 && prevdiff >= 0)) {
                    count++;
                    prevdiff = diff;
                }
            }
            return count;
        }
    }
    
  • 相关阅读:
    杭电2095--find your present (2) (异或)
    南阳168--房间安排(区间覆盖)
    南阳954--N!(数学)
    南阳--69(数的长度)
    杭电--N!(大数)
    杭电1005--Number Sequence
    杭电1108--最小公倍数
    动态规划:最长上升子序列(二分算法 nlogn)
    动态规划:最长上升子序列之基础(经典算法 n^2)
    vector函数用法
  • 原文地址:https://www.cnblogs.com/loveer/p/11788336.html
Copyright © 2020-2023  润新知