Leetcode刷题系列(六)贪心算法

  在某一个标准下, 优先考虑最满足标准的样本, 最后考虑最不满足标准的样本, 最终得到一个答案的算法, 叫作贪心算法。
  也就是说, 不从整体最优上加以考虑, 所做出的是在某种意义上的局部最优解。

如何从局部最优达到全局最优解?举反例和对数器来进行证明。

Leetcode455 分发糖果

对于给定的糖果和孩子胃口,看能最多满足多少孩子。

解题思路:将可以满足孩子的最小糖果分给该孩子,则可以使得满足的孩子数最大。

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
  		sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        
        int child = 0;
        int cookie = 0;
        while (child < g.size() && cookie < s.size()){
            if (s[cookie] >= g[child]){
                child++;
            }
            cookie++;
        }
        return child;
    }
};

Leetcode376 摇摆序列

解题思路如下

方法一:状态机模型。

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
    	if (nums.size() < 2)	return nums.size();
        
        const int BEGIN = 0;
        const int UP = 1;
        const int DOWN = 2;
        int STATE = BEGIN;
        int maxLen = 1;
        
        for (int i = 1; i < nums.size(); i++){
            switch(STATE){
                case BEGIN:
                    if (nums[i] > nums[i-1]){
                        maxLen++;
                        STATE = UP;
                    }
                    else if (nums[i] < nums[i-1]){
                        maxLen++;
                        STATE = DOWN;
                    }
                	break;
                case UP:
                    if (nums[i] < nums[i-1]){
                        maxLen++;
                        STATE = DOWN;
                    }
                    break;
                case DOWN:
                    if (nums[i] > nums[i-1]){
                        maxLen++;
                        STATE = UP;
                    }
                    break;
            }
        }
        return maxLen;
    }
};

方法二:贪心算法。遍历数组,比较当前差值与前一个差值的正负,若符号相反,序列加一,反之,继续遍历。

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
    	if (nums.size() <= 1)	return nums.size();
        
        int curDiff = 0;
        int preDiff = 0;
        int result = 1;
        for (int i = 1; i < nums.size(); i++){
            curDiff = nums[i] - nums[i-1];
            if ((curDiff >= 0 && preDiff < 0) || (curDiff <= 0 && preDiff > 0)){
                result++;
                preDiff = curDiff;
            }
        }
        
        retrurn result;
    }
};

Leetcode53 最大子序和

解题思路:

方法一:贪心算法。将数组看做多个累加和

  • 当前统计累加和,大于上一个累加和,则保存
  • 当前统计累加和,小于0(则表示该数为负值,且该负值大于当前累加和),放弃该数值,查找下一个累加和
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
    	int result = INT_MIN;
        int count = 0;
        
        for(int i = 0; i < nums.size(); i++){
            count += nums[i];
            if (count > result)		result = count;
            if (count < 0)			count = 0;
        }
    }
};

方法二:动态规划。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        vector<int> dp(nums.size(), 0);
        
        dp[0] = nums[0];		// 第1个子序和为 nums[0]
        int result = nums[0];	// 最大子序和为 nums[0]
        for (int i = 1; i < nums.size(); i++){
            // 最大子序和:当前数与前一个子序和相加 : 当前数 的最大值
            dp[i] = max(dp[i-1] + nums[i], nums[i]);
            if (result < dp[i])		result = dp[i];
        }
        return result;
    }
};

Leetcode122 买卖股票的最佳时机II

解题思路
方法一:贪心算法。在后一天收益 - 前一天收益为正时,则卖出,累积为最优收益。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
		int res = 0;
		for (int i = 1; i < prices.size(); i++){
			res += max(prices[i] - prices[i-1], 0);
 		}
		return res;
	}
};

Leetcode55 跳跃游戏

解题思路:贪心算法。将问题转化为覆盖问题,当可以覆盖最后一个数,则返回true。

class Solution {
public:
    bool canJump(vector<int>& nums) {
		int cover = 0;
	
		if (nums.size() == 1)	return true;
		for (int i = 0; i <= cover; i++){
			cover = max(i + nums[i], cover);
			if (cover >= nums.size() - 1)	return true;
		}
		return false;
	}
};

跳跃游戏II
解题思路:贪心算法。遍历数组,记录每个值的最远跳跃位置,记录该区间,在该区间内的最远跳跃位置大于记录的值,则更新该值。

class Solution {
public:
    int jump(vector<int>& nums) {
		int end = 0;
		int maxPos = 0;
		int res = 0;
		for (int i = 0; i < nums.size() - 1; i++){
			maxPos = max(nums[i] + i, maxPos);
			if (i == end){
				end = maxPos;
				res++;
			}
		}
		return res;
	}
};

练习

  1. 旋转词:KMP算法。首先将字符串本身相连,如 cdab 修改为 cdabcdab ,则新字符串任意长度为4的子串为原字符串的旋转词。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值