贪心day1

53. 最大子数组和

class Solution {
    public int maxSubArray(int[] nums) {
        int count = 0, res = Integer.MIN_VALUE;
        int len = nums.length;
        for (int i = 0; i < len; i++) {
            count += nums[i];
            //取到比前面最大值还大的值
            if (count > res) res = count;
            //如果前面和为负数,那么对只会是累赘,便从i+1开始计数
            if (count < 0) count = 0;
        }
        return res;
    }
}

亦可以使用动规解之

//动规
class Solution {
    public int maxSubArray(int[] nums) {
        int len = nums.length;
        int[] dp = new int[len];
        dp[0] = nums[0];
        int res = dp[0];
        for (int i = 1; i < len; i++) {
            //记录到i的最大连续子序列和
            dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}

分治法  对大量数据处理较优秀 可以取到任意区间的最大子数组和。

//分治 线段树
class Solution {
    private class Status {
        int iSum; //[l, r]总和
        int lSum; //[l, r]以l为端点的最大子数组和
        int rSum; //r为端点
        //求mSum需要子结点由子结点lSum 和 rSum求得
        int mSum; //[l, r]中最大子数组和
        public Status(int iSum, int lSum, int rSum, int  mSum) {
            this.iSum = iSum;
            this.lSum = lSum;
            this.rSum = rSum;
            this.mSum = mSum;
        }
    }
    public int maxSubArray(int[] nums) {
        return getInfo(nums, 0, nums.length - 1).mSum;
    }
    private Status pushUp(Status l, Status r) {
        int iSum = l.iSum + r.iSum; //由子区间总和得来
        //左子区间左端最大数组和 与 左左区间总和+右子区间左端最大数组和
        int lSum = Math.max(l.lSum, l.iSum + r.lSum);
        int rSum = Math.max(r.rSum, r.iSum + l.rSum);
        //左区间右端+右区间左端  左区间最大和 由区间最大和  取最大
        int mSum = Math.max(l.rSum + r.lSum, Math.max(l.mSum, r.mSum));
        return new Status(iSum, lSum, rSum, mSum);
    }
    private Status getInfo(int[] nums, int l, int r) {
        //[l, r]只有一个元素了,不能继续分
        if (l == r) {
            return new Status(nums[l], nums[l], nums[l], nums[l]);
        }
        int m = (l + r) / 2;
        Status lInfo = getInfo(nums, l, m);
        Status rInfo = getInfo(nums, m + 1, r);
        return pushUp(lInfo, rInfo);
    }
}

122. 买卖股票的最佳时机 II

动规解法,可恶一开始思路就是动规,贪心存在感太低了

class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        //只有一天,当天卖出利润为0
        if (len == 1) return 0;
        int[] dp = new int[len];
        dp[0] = 0;
        int res = 0;
        for (int i = 1; i < len; i++) {
            dp[i] = 0;
            if (prices[i] > prices[i - 1]) {
                //因为dp[i]由dp[i - 1]得来,也可以定义一个变量 而不用定义dp数组进行维护
                dp[i] = dp[i - 1] + prices[i] - prices[i - 1];
                //到了可买天数最后一天
                if (i == len - 1) res += dp[i];
                //如果发现当前比前一天股价低,则卖出
            } else if (prices[i] <= prices[i - 1]) { 
                res += dp[i - 1];
            }
            //System.out.println(res);
        }
        return res;
    }
}

动规2

class Solution {
    public int maxProfit(int[] prices) {
        int res = 0;
        int len = prices.length;
        //记录买入时刻
        int pre = prices[0];
        for (int i = 1; i < len; i++) {
            //卖出时机
            if (prices[i] < prices[i - 1]) {
                res += prices[i - 1] - pre;
                pre = prices[i];
            } else if (i == len - 1) {
                //最后一个交易日也应出售
                res += prices[i] - pre;
            }
        }
        return res;
    }
}

贪心,思路很巧妙

卡哥牛的

//贪心
class Solution {
    public int maxProfit(int[] prices) {
        int res = 0;
        for (int i = 1; i < prices.length; i++) {
            //有利润就卖
            res += Math.max(prices[i] - prices[i - 1], 0);
        }
        return res;
    }
}

看了官解,感觉自己的动规是野生动规。服了

//正版动规
class Solution {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len == 1) return 0;
        //dp[i][0]为第i天不持股票时剩的现金
        //dp[i][1]为第i天持有股票时剩的现金
        int dp[][] = new int[len][2];
        //第0天,不持股票现金不变,持股就要买入 减去当前股价prices[0]
        dp[0][0] = 0;
        dp[0][1] -= prices[0];
        for (int i = 1; i < len; i++) {
            //第i天 dp[i][0]:1.i-1天持股今天卖掉;2.i-1天不持股就无动作 由这两种情况结果中取最大值
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            //dp[i][1]:1.i-1天不持股今天买入;2.i-1天持股(最多只能持有一支股票)
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
        }
        return dp[len - 1][0];
    }
}

其状态转移方程

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode-s/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

参考:1.programmercarl.com

           2.https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode-s/

posted @ 2022-04-26 16:39  一梦两三年13  阅读(23)  评论(0)    收藏  举报