垃圾小白羊leetcode刷题记录3

垃圾小白羊leetcode刷题记录3_第1张图片

我的解法:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if not (p or q):
            return not bool(p)^bool(q) 
        queue = [(p, q)]
        while queue:
            t1, t2 = queue.pop(0)
            if  bool(t1) ^ bool(t2):
                return False
            if not (bool(t1) | bool(t2)):
                continue
            if t1.val != t2.val:
                return False
            queue.append((t1.left, t2.left))
            queue.append((t1.right, t2.right))

        return True

首先判别特殊情况,若两棵树一个为空一个不为空,返回False;若两棵都为空,返回True。利用元组队列遍历两颗树,比较两棵树对应节点,若对应节点不想等或一个为空一个不为空,终止循环返回False,否则继续执行,直至队列为空。

大佬解法:

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if (not p) and (not q):
            return True
        if (not p) or (not q):
            return False 
        if p.val != q.val:
            return False
    
        return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

递归算法。首先列举各种终止条件,两个节点都为空返回True,任意一个为空返回False,两个节点值不相等返回False,再递归至左右节点的相等判断。


垃圾小白羊leetcode刷题记录3_第2张图片

我的解法:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True
        queue = [(root.left, root.right)]
        while queue:
            t1, t2 = queue.pop(0)
            if (not t1) and (not t2):
                continue
            if (not t1) or (not t2):
                return False
            if t1.val != t2.val:
                return False
            queue.append((t1.left, t2.right))
            queue.append((t1.right, t2.left))

        return True

与判断相同树类似,判断根节点是否为空后,取左右子树做类似基于队列的迭代操作。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True
        def ivs_eql(lt, rt):
            if (not lt) and (not rt):
                return True
            if (not lt) or (not rt):
                return False
            if lt.val != rt.val:
                return False
            return ivs_eql(lt.left, rt.right) and ivs_eql(lt.right, rt.left)
        return ivs_eql(root.left, root.right)

递归算法,判断两子树是否对称相等。


垃圾小白羊leetcode刷题记录3_第3张图片

我的解法:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        queue = [(1, root)]
        while queue:
            depth, node = queue.pop(0)
            if node.left:
                queue.append((depth+1, node.left))
            if node.right:
                queue.append((depth+1, node.right))
        return depth

建立队列遍历树,依次压入各个节点及其对应的深度,返回遍历结束后的深度。

大佬解法:

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        return max([self.maxDepth(root.left), self.maxDepth(root.right)]) + 1

递归算法,父节点最大深度等于两子节点最大深度加一。


垃圾小白羊leetcode刷题记录3_第4张图片

我的解法:

class Solution:
    def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        queue = [(d, root)]
        vals = [[]]
        while queue:
            d, node = queue.pop(0)
            vals[d-1].append(node.val)
            if node.left:
                queue.append((d+1, node.left))
            if node.right:
                queue.append((d+1, node.right))
            if (node.left or node.right) and len(vals)<=d+1:
                vals.append([])
        return vals[::-1]

实际为自顶向下遍历再倒转。利用记录树深度的队列自顶向下遍历树,遍历同时将不同深度的节点值记录到嵌套列表中。每层遍历中若深度增加,则在嵌套列表中再添加一个新列表以储存下一深度节点值。


垃圾小白羊leetcode刷题记录3_第5张图片
我的解法:

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
        if len(nums) == 0:
            return None
        n = len(nums)
        node = TreeNode(nums[n//2])
        node.left = self.sortedArrayToBST(nums[:n//2])
        node.right = self.sortedArrayToBST(nums[n//2+1:])
        return node

递归算法,利用平衡二叉搜索树的子树也是平衡二叉搜索树,每层递归定义一个父节点。


垃圾小白羊leetcode刷题记录3_第6张图片

我的解法:

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        def depth(node):
            if not node:
                return 0
            return max([depth(node.left), depth(node.right)])+1
            
        if not root:
            return True
        return (abs(depth(root.left)-depth(root.right)) < 2) and (self.isBalanced(root.left)) and (self.isBalanced(root.right))

定义函数depth计算树的深度,基本思路为树深度为两子树深度最大值加1。若树为平衡二叉树,则每个树节点的左右子树深度之差小于等于1。因此需要递归判断各节点对应子树的左右子树高度差是否小于等于1,且左右子树都为平衡二叉树。深度计算时间复杂度为logn, 遍历节点时间复杂度n,总时间复杂度O(nlogn)。

大佬解法:

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:

        def helper(node):
            if not node:
                return 0
            left = helper(node.left)
            if left == -1: 
                return -1
            right = helper(node.right)
            if right == -1: 
                return -1
            return max([left+1, right+1]) if abs(left-right)<2 else -1

        if not root:
            return True
        return helper(root) != -1

在计算子树高度时,同时判断该子树是不是平衡二叉树,若不是高度记为-1。若某树的子树高度为-1,整棵树的高度也为-1,那么整棵树不是平衡二叉树。


垃圾小白羊leetcode刷题记录3_第7张图片
我的解法:

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        if root.left and not root.right:
            return self.minDepth(root.left)+1
        if not root.left and root.right:
            return self.minDepth(root.right)+1
        
        return min([self.minDepth(root.left)+1, self.minDepth(root.right)+1])

递归算法。对任意节点,若它的左右子节点都存在,它的最小深度为左右子节点最小深度较小值加1;若左右子节点只有一个存在,它的最小深度为存在节点最小深度加1;若无子节点,其最小深度为1。


垃圾小白羊leetcode刷题记录3_第8张图片

我的解法:

class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        if not root:
            return False
        queue = [(root.val, root)]
        while queue:
            s, node = queue.pop(0)
            if (s == sum) & ((not node.left) & (not node.right)):
                return True
            if node.left:
                queue.append((s+node.left.val, node.left))
            if node.right:
                queue.append((s+node.right.val, node.right))
        return False

遍历整棵树,每个节点记录自根节点始到当前节点的加和值,若该节点加和值等于目标值且该节点为叶节点,返回True,否则继续遍历,直至最终无满足条件节点,返回False。

class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        if not root:
            return False
        sum -= root.val
        if (sum == 0) and (not root.left) and (not root.right):
            return True
        return self.hasPathSum(root.left, sum) or self.hasPathSum(root.right, sum)

递归算法,判断当前节点是否是叶节点且满足sum条件,若不满足则用sum减去当前节点值分别作为左右子节点的目标值递归调用本函数。


垃圾小白羊leetcode刷题记录3_第9张图片

class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        tri_list = [[1]]
        for i in range(1,numRows):
            new_row = tri_list[i-1]+[0]
            for j in range(1,len(new_row)):
                new_row[j] += tri_list[i-1][j-1]
            tri_list.append(new_row)
        return tri_list[:numRows]

利用杨辉三角的每行为上一行的错一位相加,逐层产生杨辉三角每一层输出。


垃圾小白羊leetcode刷题记录3_第10张图片

我的解法:

class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        l = [1]
        for k in range(0, rowIndex): 
            l += [1]
            for i in range(k,0,-1):
                l[i] = l[i]+l[i-1]
        return l

动态规划,每层除第一和最后一个元素外,第i个元素的更新可以满足l[i] = l[i] + l[i-1],为了防止前一位元素的更新对后续元素更新的影响,每层元素更新时,采用从后往前更新。


垃圾小白羊leetcode刷题记录3_第11张图片
我的解法:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0
        min_num = prices[0]
        profit, max_prf = 0, 0
        for i in range(1, len(prices)):
            if prices[i] < min_num:
                min_num = prices[i]
            else:
                profit = prices[i] - min_num
                max_prf = max([profit, max_prf])
        return max_prf

遍历一遍数组找到最大利润,关键在于记录更新遍历过程中的当前最小值以及当前最大利润。若遍历到的元素小于当前最小值,则更新当前最小值,其余情况下计算当前遍历到的元素与当前最小值的差,更新差的最大值记录。时间复杂度O(n)。


垃圾小白羊leetcode刷题记录3_第12张图片
我的解法:

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        d = {
     }
        for num in nums:
            if not d.get(num):
                d[num] = 1
            else:
                d[num] += 1

        for n in d:
            if d[n] == 1:
                return n

遍历数组,用字典记录每个值出现的次数,再遍历一次字典,返回值为1的元素,时间复杂度O(n),空间复杂度O(n)。

大佬解法:

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        return reduce(lambda x,y: x^y, nums)

运用亦或位运算,利用性质a⊕a = 0, a⊕0 = a,最终唯一元素结果即为a1⊕a2⊕…⊕an。时间复杂度O(n),空间复杂度O(1)。


垃圾小白羊leetcode刷题记录3_第13张图片

我的解法:

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if not head:
            return

        d = {
     head:1}
        while 1:
            if head.next is None:
                return False
            elif d.get(head.next):
                return True
            else:
                d[head.next] = 1
                head= head.next

遍历链表,利用字典记录出现过的节点,若遍历到的节点存在于字典中,则该链表存在环;若遍历到None,则该链表不存在环。时间复杂度O(n),空间复杂度O(n)。

大佬解法:

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if not head:
            return
        p, q = head, head
        while 1:
            if (q is None) or (q.next is None):
                return False
            q = q.next.next
            p = p.next
            if p == q:
                return True

使用双指针,其中一个指针一次向前移动一格,另一个一次向前移动两格。若快指针遇到None,则该链表中没有环;若快指针与慢指针重合,则说明链表中有环,快指针追上了慢指针。时间复杂度O(n),空间复杂度O(1)。


垃圾小白羊leetcode刷题记录3_第14张图片

我的解法:

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        na, nb, A, B = 0, 0, headA, headB
        while A:
            na += 1
            A = A.next
        while B:
            nb += 1
            B = B.next

        if na >= nb:
            for i in range(0,na-nb):
                headA = headA.next

        else:
            for i in range(0,nb-na):
                headB = headB.next
        
        while 1:
            if not (headA or headB):
                return None
            if headA == headB:
                return headA

            headA = headA.next
            headB = headB.next

首先分别遍历两链表,分别得到两个链表的长度,长度较长的链表头指针向后移动,保证两个链表长度相同后开始同时遍历,一一比对各自的节点,若出现相同节点,则返回当前节点;若到链表尾仍然没有出现相同节点,返回None。时间复杂度O(n+m),空间复杂度啊O(1)。

大佬解法:

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        pA, pB = headA, headB
        while 1:
            if pA == pB:
                return pA
            if (not pA) and (not pB):
                return
            if not pA:
                pA = headB
                pB = pB.next
            elif not pB:
                pB = headA
                pA = pA.next
            else:
                pA = pA.next
                pB = pB.next

神奇解法,当pA遍历到链表尾后,指向B链表头部,当pB遍历到链表尾后,指向A链表头部。当较长链表指针指向较短链表头部后,两链表待比较长度相同,此时再遍历一遍短链表即可判断是否为相交链表。时间复杂度O(n+m),空间复杂度啊O(1)。(其实和我的解法是一样的,还是我的解法更好懂啊!)

你可能感兴趣的:(小白羊不太会编程,leetcode,二叉树,算法)