Day10 LeetCode121 122 124(JAVA版)

这篇博客介绍了LeetCode中关于股票交易的最佳时机(121题和122题)及二叉树中最大路径和(124题)的解题思路和代码实现。对于股票问题,通过优化算法从暴力解法到单遍历求解,降低时间复杂度。在二叉树问题中,利用递归策略寻找最大路径和,确保路径的有效性。
摘要由CSDN通过智能技术生成

目录

1. 买卖股票的最佳时机(LeetCode 121 题)

1.1题目

1.2思路

1.3代码

2. 买卖股票的最佳时机 II(LeetCode 122 题)

2.1题目

2.2思路

2.3代码

3. 二叉树中的最大路径和(LeetCode 124题)

3.1题目

3.2思路

3.3代码

4.参考资料


1. 买卖股票的最佳时机(LeetCode 121 题)

1.1题目

1.2思路

方法一

暴力解法当然是二重循环,一个指针从头开始逐个遍历为i。另一个指针为i+1到末尾。找到最大的距离。

但是非常不幸,这段代码超时了。不过基本解题思路是明确的。被卡住的测试用例我截图在上面……分析一下时间复杂度为什么会超时。

我们循环两层,那么我们内层循环从n-1(近似看为n次)开始到1。总共有n次 。也就是n(n+1)/2次,为n2。

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length<=1) return 0;
        int maxout = 0;
        for(int i =0;i<prices.length-1;i++){
            for(int j =i+1;j<prices.length;j++){
                if(prices[j]>prices[i]) maxout=maxout>prices[j]-prices[i]?maxout:prices[j]-prices[i];
            }
        }
        return maxout;
    }
}

方法二

我们采用时间复杂度为n的方法来解决这个问题。具体应该如何入手呢?

我们看一下官方给的方法并加以补充解释。

Profit Graph

我们来假设自己来购买股票。随着时间的推移,每天我们都可以选择出售股票与否。那么,假设在第 i 天,如果我们要在今天卖股票,那么我们能赚多少钱呢?

显然,如果我们真的在买卖股票,我们肯定会想:如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录一个历史最低价格 minprice,我们就可以假设自己的股票是在那天买的。那么我们在第 i 天卖出股票能得到的利润就是 prices[i] - minprice。

因此,我们只需要遍历价格数组一遍,记录历史最低点,然后在每一天考虑这么一个问题:如果我是在历史最低点买进的,那么我今天卖出能赚多少钱?当考虑完所有天数之时,我们就得到了最好的答案。[1]

官方的方法是建议我们每次从历史最低价格开始,这里写的其实不够明确容易让人误解,准确的说法是当前的历史最低价,而不是整体的历史最低价

如果我们出现了当前的历史最低价,我们把历史最低价放入minprice,否则不是当前的最低价(也就是暂时没有出现比我们之前的最低值还要低的)。

后面凡是出现高于最低价的值必然高于这之间的值,也就是我们N2方法的重复计算值,这种思路可以有效的舍去这些多余的部分。

接着我们可能会出现这样的情况,

如果我们最后的走势是一路下跌,我们不管怎么更新最小值都不会影响整体的最大收入。

同时即使l2的起点低于l1,但每次比较最大的收入即可得到最大的值,简化计算并不会影响的到正确结论。

1.3代码

class Solution {
    public int maxProfit(int[] prices) {
        int minprice =prices[0];
        int maxout = 0;
        for(int i =0;i<prices.length;i++){
            if(prices[i]<minprice){
                minprice = prices[i];
            }else if(prices[i]-minprice>maxout){
                maxout = prices[i]-minprice;
            }
        }
        return maxout;
    }
}

2. 买卖股票的最佳时机 II(LeetCode 122 题)

2.1题目

 

 

 

2.2思路

接上题的思路,我们可以把本题拆成很多段最大抛售的和的结果

这也是本题的核心思想。那么我们怎么找到这些最大抛售的拆分点呢?也很简单,如果股票跌了,我们都想有特异功能,回到昨天抛掉之前的股票。

那么在本题中,如果[i+1]值小于[i]我们实现抛售操作即可。同时小心指针超范围哦。

抛售操作具体做什么,更新最大抛售额为0(实现本质的抛售操作),就是局部最小值至为当前的第一个点的值,同时更新总值(首先判断我们后面是否还有数据,也就是判断数组指针是否合法)。

本解法的时间复杂度为N,空间复杂度为1。

2.3代码

class Solution {
    public int maxProfit(int[] prices) {
        int minprice =prices[0];
        int maxout = 0;
        int maxp = 0;
        for(int i =0;i<prices.length;i++){
            if(prices[i]<minprice){
                minprice = prices[i];
            }else if(prices[i]-minprice>maxp){
                maxp = prices[i]-minprice;
            }
            if(i+1<prices.length&&prices[i]>prices[i+1]){
                maxout += maxp;
                maxp = 0;
                minprice = prices[i+1];
                continue;
            }
        }
        if(maxp!=0) maxout += maxp;
        return maxout;
    }
}

3. 二叉树中的最大路径和(LeetCode 124题)

3.1题目

 

3.2思路

本题为求得最大路径和。也就是说我们求得的路径除了首部可以连接左右子树,其左右子树必须为单链子树。

我们可以通过递归的方法解答这道题。同时采用max的变量来记录最大的路径值。

从根部出发,遍历左右子树的val值,选择子树的最大路径。之后计算左右子树的最大路径以及根的和。同时刷新max。遍历完整棵树即可得到最大路径的值、

如果左右子树求得的val为负,我们可以直接将左子树或者右子树值赋值为0。

当我们向下遍历时应该注意我们的return值只能是单链的,因此我们返回root.val+Math.max(leftval+rightval)。而我们向下遍历的同时也可以顺便求得子树的最大路径值。

一个递归两个作用。这样就有了以下的代码,非常巧妙。[2]

3.3代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int maxSum = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        maxPathSum1(root) ;
        return maxSum;
    }
    public int maxPathSum1(TreeNode root) {
        if(root == null) return 0;
        int leftval = Math.max(maxPathSum1(root.left),0);
        int rightval = Math.max(maxPathSum1(root.right),0);
        int maxp = leftval+rightval+root.val;
        maxSum = Math.max(maxSum,maxp);
        // 这里为子路径,子路径和根路径的计算有所不同,
        //如果根路径可以算入任意位置为起点,但是子路径只能选择其中一颗子树。

        //这里如果需要递归,就不能包含其中子节点的所有左右节点,只能选择其中的路径。
        return root.val+Math.max(leftval,rightval);
    }
}

4.参考资料

[1].https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/121-mai-mai-gu-piao-de-zui-jia-shi-ji-by-leetcode-/

[2].https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/solution/er-cha-shu-zhong-de-zui-da-lu-jing-he-by-leetcode-/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值