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

前言

贪心算法(又称贪婪算法)是指:
    在对问题求解时,总是做出局部最优解。


贪心算法的基本思路:

    根据某个优化测度,每一步都要确保能获得局部最优解。
    每一步只考虑一个数据,他的选取应该满足局部优化的条件。

    若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完。


贪心策略适用的前提是:
    局部最优策略能导致产生全局最优解。

跳跃游戏

/**
 * 给定一个非负整数数组,你最初位于数组的第一个位置。
 * 
 * 数组中的每个元素代表你在该位置可以跳跃的最大长度。
 * 
 * 判断你是否能够到达最后一个位置。
 * 
 * 思路:贪心法
 *      循环数组,如果可以达到的最大位置<当前位置,返回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;
    }
}

猜你喜欢

转载自www.cnblogs.com/loveer/p/11788336.html