牛客刷题day5(链表中环的入口节点,删除链表中重复元素,平衡二叉树,股票交易两次交易和不限制交易次数,二叉树根节点到子节点等于制定的数)

牛客刷题day5

1.链表中环的入口节点

题目

对于一个给定的链表,返回环的入口节点,如果没有环,返回null
拓展:
你能给出不利用额外空间的解法么?

解题思路

快慢指针方法:将两指针分别放在链表头(X)和相遇位置(Z),并改为相同速度推进,则两指针在环开始位置相遇(Y),如图所示。
在这里插入图片描述
快指针与慢指针均从X出发,在Z相遇。此时,慢指针行使距离为a+b,快指针为a+b+n(b+c)。
所以2*(a+b)=a+b+n*(b+c),推出
a=(n-1)b+nc=(n-1)(b+c)+c;
得到,将此时两指针分别放在起始位置和相遇位置,并以相同速度前进,当一个指针走完距离a时,另一个指针恰好走出 绕环n-1圈加上c的距离。也就是说二者又会在Y点相遇,而Y点就是环的入口。
判断链表是否有环有三种方法,这种方法最巧妙也是最常见的。具体的可参照博客 ,里面详细介绍了三种方法。判断链表中是否有环的三种方法

核心代码
class Solution:
    def detectCycle(self, head):
        if not head or not head.next:
            return
            # write code here
        slow = head
        fast = head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if slow == fast:
                fast = head
                while fast != slow:
                    fast = fast.next
                    slow = slow.next
                return slow
        return
        

2. 删除有序链表中的重复元素

题目

删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次
例如:
给出的链表为1→1→2,返回1 1→2.
给出的链表为1→1→2→3→3,返回1→2→3.

解题思路

直接遍历链表,删除重复元素即可

class Solution:
    def deleteDuplicates(self, head):
        if not head:
            return head
        p = head
        while p.next:
            if p.val== p.next.val:
                p.next= p.next.next
            else:
                p = p.next
        return head

3.平衡二叉树

题目

输入一棵二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树

解题思路

判断一个数是否为平衡二叉树。平衡二叉树是左子树的高度与右子树的高度差的绝对值小于等于1,同样左子树是平衡二叉树,右子树为平衡二叉树。

根据定义,如果我们能够求出以每个结点为根的树的高度,然后再根据左右子树高度差绝对值小于等于1,,就可以判断以每个结点为根的树是否满足定义

核心代码
class Solution:
    def IsBalanced_Solution(self, pRoot):
        if not pRoot:
            return True
        leftDepth = self.depth(pRoot.left)
        rightDepth = self.depth(pRoot.right)
        depth = abs(leftDepth - rightDepth)
        if depth <=1 and self.IsBalanced_Solution(pRoot.left)and self.IsBalanced_Solution(pRoot.right):
            return True
        return False

    def depth(self, root):
        if not root:
            return 0
        depth = max(self.depth(root.left), self.depth(root.right)) + 1
        return depth
        

4.股票无数次交易获得最大收益

题目

假定你知道某只股票每一天价格的变动。
你最多可以同时持有一只股票。但你可以无限次的交易(买进和卖出均无手续费)。
请设计一个函数,计算你所能获得的最大收益。

解题思路

只要第二天卖出价格大于第一天买入价格就能获得利润
不限制交易次数 只要将获得利润全部相加就能保证利润最大化(第二天价格大于第一天价格)

核心代码
class Solution:
    def maxProfit(self , prices ):
        # write code here
        if not prices:
            return 0
        profit = 0
        for i,price in enumerate(prices):
            if i>0 and price>prices[i-1]:
                profit+=price-prices[i-1]
                
        return profit
        

5. 股票交易最大收益(只能进行两次交易)

题目:

假定你知道某只股票每一天价格的变动。
你最多可以同时持有一只股票。但你最多只能进行两次交易(一次买进和一次卖出记为一次交易。买进和卖出均无手续费)。
请设计一个函数,计算你所能获得的最大收益
输入:[8,9,3,5,1,3]
输出:4
备注:第三天买进,第四天卖出,第五天买进,第六天卖出。总收益为4。

解题思路

这个题其实考察的就是动态规划的思想:
通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决
我们仔细分解这个问题:
首先要取得最大利润,那么第一次和第二次的利润都最大,而股票第二次交易是建立在第一次交易上,第一次交易利润越高,那么第二次购入股票成本最低,将整个问题分解:
第一次购入股票:如果第一次成本最低,要么就是当天的价格,要么就是取整个交易过程中价格最低的那一天
第一次利润最大:要么就是取交易过程中利润最大的 要么就是当日交易价格减去第一次的成本价
第二次交易是建立在第一次之上的:
第二次购入股票成本价:第二次买入的成本就是当前买入的价格减去第一次交易所赚取的利润
那么第二次交易完总利润最大:第二次卖出股票价格减去第二次购入股票最小的成本
那么整个过程中只要执行上面交易规则,最后的利润一定是最大的

核心代码:
class Solution:
    def maxProfit(self , prices ):
        # write code here
        buy1 = buy2 = float('inf')
        profit_buy1 = profit_all = 0
        for price in prices:
            # 第一次买入要求买入的成本最低
            # 如果第一次成本最低,要么就是当前的价格,要么就是取整个交易过程中价格最低的那一天
            buy1 = min(buy1,price)
            # 要求第一次利润最大
            # 要么就是取交易过程中利润最大的 要么就是当日交易价格减去第一次的成本价
            profit_buy1 =max(profit_buy1,price-buy1)
            
            #第二次买入的成本价就是当前买入的价格减去第一次交易所赚取的利润
            buy2 = min(buy2,price-profit_buy1)
            # 总利润 就是 当前卖出价格减去第一次的成本价
            profit_all = max(profit_all, price-buy2)
        return profit_all

6.二叉树根节点到子节点等于指定的数字

题目:

给定一个二叉树和一个值sum,请找出所有的根节点到叶子节点的节点值之和等于 sum 的路径,
例如:
给出如下的二叉树, sum=22
在这里插入图片描述
返回
[[5,4,11,2],[5,8,9]]

解题思路

使用二叉树的先序遍历进行递归就好

核心代码
class Solution:                                                                  
    def pathSum(self, root, sum):                                                
        # write code here                                                        
        if not root:                                                             
            return []                                                            
        res = []                                                                 
        current = 0                                                              
        path = []                                                                
        self.preOrder(root, sum, res, [root.val], current)                       
        return res                                                               
                                                                                 
    def preOrder(self, root, sum, res, path, current):                           
        if not root:                                                             
            return                                                               
        current += root.val                                                      
        if sum == current and not root.left and not root.right:                  
            res.append(path)                                                     
        if root.left:                                                            
            self.preOrder(root.left, sum, res, path + [root.left.val], current)  
        if root.right:                                                           
            self.preOrder(root.right, sum, res, path + [root.right.val], current)
                                                                           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值