局部全局思路总结

Maximum Subarray III

Given an array of integers and a number k, find k non-overlapping subarrays which have the largest sum.

The number in each subarray should be contiguous.

Return the largest sum.

Notice

The subarray should contain at least one number

class Solution {
public:
    /**
     * @param nums: A list of integers
     * @param k: An integer denote to find k non-overlapping subarrays
     * @return: An integer denote the sum of max k non-overlapping subarrays
     */
    int maxSubArray(vector<int> &nums, int k) {
        // write your code here
        // return maxSubArray1(nums, k);
        return maxSubArray2(nums, k);
    }
    /* local + global
     * 边界条件,就是当k为0时应该是0,当其他非法情况时为INT_MIN。理解这个是难点
     * 和最佳买卖股票时间那道题相似
     */
    int maxSubArray1(vector<int> &nums, int k) {
        // write your code here
        if (nums.size() == 0 || k == 0 || k > nums.size()) {
            return 0;
        }
        int n = nums.size();
        vector<vector<int>> local(n + 1, vector<int>(k + 1, INT_MIN));
        vector<vector<int>> global(n + 1, vector<int>(k + 1, INT_MIN));
        // init
        for (int i = 0; i <= n; i++) {
            global[i][0] = 0;
            local[i][0] = 0;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= k && j <= i; j++) {
                local[i][j] = max(global[i - 1][j - 1],local[i - 1][j]) + nums[i - 1];
                global[i][j] = max(global[i - 1][j], local[i][j]);
            }
        }
        return global[n][k];
    }
    /* 这题属于动态规划里比较难的一题。首先定义状态,f[i][j]表示:在前i个元素中取出j个不重叠的子数组的和的最大值(也就
     * 要将前i个元素组成的数组划分成j个部分,每个部分求最大子数组,然后相加)。状态定义好了之后,需要找到状态之间的关
     * ,也就是求动态转移方程。可以将f[i][j]拆分成两部分来看,第一部分是f[x][j - 1],x为j - 1~ i
     * - 1之间的任意值,表示前x个元素中取j - 1个子数组的和的最大值。第二部分是[x, x + 1, ..., i -
     * 1]数组,求这个数组的maximum subarray(可以理解为在数组[0, 1, ..., x - 1, x, ..., i-
     * 1]中任意切一刀,分成两部分。index为x - 1的地方就是那一刀切的地方,第一部分是[0, 1, ..., x - 1],第二部分是[x, x +
     * 1, ..., i - 1])。由此得到动态转移方程为:f[i][j] = f[x][j - 1] + maxSubarray([x, x + 1, ..., i - 1])。求max
     * subarray的方法可以参考maximum subarray那道题。
     */
    int maxSubArray2(vector<int> &nums, int k) {
        // write your code here
        if (nums.size() == 0 || k == 0 || k > nums.size()) {
            return 0;
        }
        int n = nums.size();
        vector<vector<int>> dp(n + 1, vector<int>(k + 1, INT_MIN));
        // init
        for (int i = 0; i <= n; i++) {
            dp[i][0] = 0;
        }
        for (int j = 1; j <= k; j++) {
            for (int i = j; i <= n; i++) {
                int cur_sum = 0;
                int max_sum = INT_MIN;
                for (int x = i - 1; x >= j - 1; x--) {
                    cur_sum = max(cur_sum + nums[x], nums[x]);
                    max_sum = max(max_sum, cur_sum);
                    dp[i][j] = max(dp[i][j], dp[x][j - 1] + max_sum);
                }
            }
        }
        return dp[n][k];
    }
};
class Solution {
public:
    /**
     * @param nums: A list of integers
     * @param k: An integer denote to find k non-overlapping subarrays
     * @return: An integer denote the sum of max k non-overlapping subarrays
     */
    int maxSubArray(vector<int> &nums, int k) {
        // write your code here
        int n = nums.size();
        if (n == 0 || k == 0 || n < k) {
            return 0;
        }
        // avoid overflow, use long long
        vector<vector<long long>> global(n + 1, vector<long long>(k + 1, INT_MIN));
        vector<vector<long long>> local(n + 1, vector<long long>(k + 1, INT_MIN));
        // init
        for (int i = 0; i <= n; i++) {
            global[i][0] = 0;
            local[i][0] = 0;
        }
        for (int i = 1; i <= n; i++) {
            // if no condition to j <= i, INT_MIN + nums[i - 1] will overflow
            for (int j = 1; j <= k; j++) {
                local[i][j] = max(global[i - 1][j - 1], local[i - 1][j]) + nums[i - 1];
                global[i][j] = max(global[i - 1][j], local[i][j]);
            }
        }
        return global[n][k];
    }
};


Best Time to Buy and Sell Stock IV

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most k transactions.

Notice

You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

Example

Given prices = [4,4,6,1,1,4,2,5], and k = 2, return 6.

class Solution {
public:
    /**
     * @param K: An integer
     * @param prices: An integer array
     * @return: Maximum profit
     */
    int maxProfit(int K, vector<int> &prices) {
        // write your code here
        return maxProfit2(K, prices);
    }
    int maxProfit1(int K, vector<int> &prices) {
        // write your code here
        if (K == 0 || prices.size() < 2) {
            return 0;
        }
        int maxprofit = 0;
        if (K >= prices.size()) {
            for (int i = 1; i < prices.size(); i++) {
                if (prices[i] > prices[i - 1]) {
                    maxprofit += (prices[i] - prices[i - 1]);
                }
            }
            return maxprofit;
        }
        int n = prices.size();
        vector<vector<int>> global(n, vector<int>(K + 1, 0));
        vector<vector<int>> local(n, vector<int>(K + 1, 0));
        for (int i = 1; i < n; i++) {
            int diff = prices[i] - prices[i - 1];
            for (int j = 1; j <= K; j++) {
                local[i][j] = max(global[i - 1][j - 1] + max(0, diff), local[i - 1][j] + diff);
                global[i][j] = max(global[i - 1][j], local[i][j]);
            }
        }
        return global[n - 1][K];
    }
    int maxProfit2(int K, vector<int> &prices) {
        // write your code here
        if (K == 0 || prices.size() < 2) {
            return 0;
        }
        int maxprofit = 0;
        if (K >= prices.size()) {
            for (int i = 1; i < prices.size(); i++) {
                if (prices[i] > prices[i - 1]) {
                    maxprofit += (prices[i] - prices[i - 1]);
                }
            }
            return maxprofit;
        }
        int n = prices.size();
        vector<vector<int>> buy(n + 1, vector<int>(K + 1, INT_MIN));
        vector<vector<int>> sell(n + 1, vector<int>(K + 1, 0));
        for (int i = 1; i <= prices.size(); i++) {
            for (int j = 1; j <= K; j++) {
                buy[i][j] = max(buy[i - 1][j], sell[i][j - 1] - prices[i - 1]);
                sell[i][j] = max(sell[i - 1][j], buy[i][j] + prices[i - 1]);
            }
        }
        return sell[n][K];
    }
};
class Solution {
public:
    /**
     * @param K: An integer
     * @param prices: An integer array
     * @return: Maximum profit
     */
    int maxProfit(int K, vector<int> &prices) {
        // write your code here
        int n = prices.size();
        if (K == 0 || n == 0) {
            return 0;
        }
        if (K >= n) {
            int max = 0;
            for (int i = 1; i < n; i++) {
                max += (prices[i] > prices[i - 1] ? prices[i] - prices[i - 1] : 0);
            }
            return max;
        }
        vector<vector<int>> local(n + 1, vector<int>(K + 1, 0));
        vector<vector<int>> global(n + 1, vector<int>(K + 1, 0));
        // at least need two
        for (int i = 2; i <= n; i++) {
            int diff = prices[i - 1] - prices[i - 2];
            for (int k = 1; k <= K; k++) {
                // why global can select max(0, diff) ? because for global the kth can independent to k-1
                // why local need directly diff? because for local, the kth is from last kth
                // need need local[i - 1][k - 1] as it always <= global[i - 1][k - 1]
                local[i][k] = max(global[i - 1][k - 1] + max(0, diff), local[i - 1][k] + diff);
                global[i][k] = max(global[i - 1][k], local[i][k]);
            }
        }
        return global[n][K];
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值