Algorithms: Greedy

3 minute read

Published:

动态规划: 每一步都进行选择,依赖于子问题的解。通常使用自底向上求解,先求较小的子问题,然后是较大的子问题。

贪心: 每次找出局部最优解。

122. Best Time to Buy and Sell Stock II

  • 可以无限次买入卖出
  • 最优子结构:res += max(0, prices[i] - prices[i-1])
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int res = 0;
        for (auto i = 1; i < prices.size(); ++i) 
            res += max(0, prices[i] - prices[i-1]);
        return res;
    }
};

55. Jump Game

Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Determine if you are able to reach the last index.
For example:
A = [2,3,1,1,4], return true.
A = [3,2,1,0,4], return false.
  • 求是否能到达数组的最后位置。
class Solution {
public:
    bool canJump(vector<int>& nums) {
        int reach = 0;
        for (auto i = 0; i != nums.size() && i <= reach; ++i) {
            reach = max(reach, nums[i] + i);
        }

        return reach >= nums.size() - 1;
    }
};

45. Jump Game II

Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A = [2,3,1,1,4]
The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)
Note:
You can assume that you can always reach the last index.
  • 与44题相似,不过要求到达最后一个位置的最小跳数。
  • 局部最优解:求出当前点能到达的最远距离,在该范围内count不更新。
class Solution {
public:
    int jump(vector<int>& nums) {
        int reach = 0, count = 0, next = 0;
        for (auto i = 0; i < nums.size() - 1; ++i) {
            reach = max(reach, i + nums[i]);
            if (i == next) {
                count++;
                next = reach;
            }
        }
        return count;
    }
};

134. Gas Station

There are N gas stations along a circular route, where the amount of gas at station i is gas[i].
You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.
Return the starting gas station's index if you can travel around the circuit once, otherwise return -1.
Note:
The solution is guaranteed to be unique.
  • 如果所有gas >= 所有cost,则结果存在;且起始点为剩余油量最少的下一个。
  • 最优子结构:total = min(total, total + gas[i] - cost[i])。找出剩余油量最少的下一个.
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
    int n = gas.size();
    int total = 0, subsum = INT_MAX, start = 0;
    for (int i = 0; i < n; ++i) {
        total += (gas[i] - cost[i]);
        if (total < subsum) {
            subsum = total;
            start = i + 1;
        }
    }

    return (total >= 0) ? start%n : -1;
}

135. Candy

There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?

分为如下步骤进行

  • 初始化为每个小孩都有1块糖
  • 从前往后遍历,保证如果后一个的rate大,则分的糖也比前一个多1个
  • 从后往前遍历,保证如果前一个的rate大,则分的糖取max(当前, 后一个+1)
  • 最优子结构:左边比当前大,则左边+1。右边比当前大,则右边+1。
int candy(vector<int>& ratings) {
    if (ratings.size() <= 1) return ratings.size();

    int res = 0;
    vector<int> counts(ratings.size(), 1);
    for (auto i = 0; i < ratings.size() - 1; ++i) {
        if (ratings[i + 1] > ratings[i])
            counts[i + 1] = counts[i] + 1;
    }

    for (auto i = ratings.size() - 1; i > 0; --i) {
        if (ratings[i - 1] > ratings[i])
            counts[i - 1] = max(counts[i - 1], counts[i] + 1);
    }

    for (auto n:counts)
        res += n;
    return res;
}