前言
贪心算法(又称贪婪算法)是指:
在对问题求解时,总是做出局部最优解。
贪心算法的基本思路:
根据某个优化测度,每一步都要确保能获得局部最优解。
每一步只考虑一个数据,他的选取应该满足局部优化的条件。
若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完。
贪心策略适用的前提是:
局部最优策略能导致产生全局最优解。
跳跃游戏
/**
* 给定一个非负整数数组,你最初位于数组的第一个位置。
*
* 数组中的每个元素代表你在该位置可以跳跃的最大长度。
*
* 判断你是否能够到达最后一个位置。
*
* 思路:贪心法
* 循环数组,如果可以达到的最大位置<当前位置,返回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;
}
}