• leetcode刷题-106~114/116~122/125/127/129~130


    题目106题

    从中序与后序遍历序列构造二叉树

    根据一棵树的中序遍历与后序遍历构造二叉树。

    注意:
    你可以假设树中没有重复的元素。

    例如,给出

    中序遍历 inorder = [9,3,15,20,7]
    后序遍历 postorder = [9,15,7,20,3]
    返回如下的二叉树:

         3
        /
       9 20
          /
         15  7

    思路

    与105题基本一致

    实现

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
            def build(in_left, in_right, po_left, po_right):
                if in_left > in_right:
                    return None
                new_root = postorder[po_right]
                root = TreeNode(new_root)
                index = inorder.index(new_root)
                right_len = in_right - index
                root.left = build(in_left, index-1, po_left, po_right - right_len -1)
                root.right = build(index+1, in_right, po_right - right_len,po_right-1)
                return root
            n = len(inorder) - 1
            return build(0,n,0,n)

    题目107题

    二叉树的层次遍历 II

    给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

    例如:
    给定二叉树 [3,9,20,null,null,15,7],

      3
         /
        9 20
       /
      15 7
    返回其自底向上的层次遍历为:

    [
    [15,7],
    [9,20],
    [3]
    ]

    思路

    与102题完全一致,只是将层数颠倒

    实现

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
            def helper(node: TreeNode, result, lev):
                if node:
                    if len(result) <= lev:
                        result.insert(0, [])
                    size = len(result)
                    result[size - lev -1].append(node.val)
                    if node.left:
                        helper(node.left, result,lev+1)
                    if node.right:
                        helper(node.right, result,lev+1)
    
            level = 0
            result = []
            helper(root, result, level)
            return result

    题目108题

    将有序数组转换为二叉搜索树

    将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

    本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

    示例:

    给定有序数组: [-10,-3,0,5,9],

    一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

      0
       /
      -3   9
     /   /
    -10 5

    思路

    平衡二叉查找树:简称平衡二叉树。由前苏联的数学家 Adelse-Velskil 和 Landis 在 1962 年提出的高度平衡的二叉树,根据科学家的英文名也称为 AVL 树。它具有如下几个性质:

    1. 可以是空树。
    2. 假如不是空树,任何一个结点的左子树与右子树都是平衡二叉树,并且高度之差的绝对值不超过 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 sortedArrayToBST(self, nums: List[int]) -> TreeNode:
            def helper(left,right):
                if left > right:
                    return None
                mid = (left + right + 1)//2
                root = TreeNode(nums[mid])
                root.left = helper(left, mid -1)
                root.right = helper(mid+1, right)
                return root
            
            return helper(0, len(nums)-1)

    题目109

    有序链表转换二叉搜索树

    给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。

    本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

    示例:

    给定的有序链表: [-10, -3, 0, 5, 9],

    一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:

            0
           /
        -3   9
        /    /
    -10    5

    思路

    此题思路与108题完全一致,但是由于这是单项链表,因此需要使用快慢指针法找到中间点

    实现

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, val=0, left=None, right=None):
    #         self.val = val
    #         self.left = left
    #         self.right = right
    class Solution:
        def sortedListToBST(self, head: ListNode) -> TreeNode:
            def midnode(left,right):
                fast = slow = left
                while fast != right and fast.next != right:
                    fast = fast.next.next
                    slow = slow.next
                return slow
    
            def helper(left,right):
                if left == right:
                    return None
                mid = midnode(left, right)
                root = TreeNode(mid.val)
                root.left = helper(left, mid)
                root.right = helper(mid.next, right)
                return root
            return helper(head, None)

    题目110 

    平衡二叉树

    给定一个二叉树,判断它是否是高度平衡的二叉树。

    本题中,一棵高度平衡二叉树定义为:

    一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

    思路

    1.自顶向下:

    计算节点高度的函数,即可判断二叉树是否平衡。计算当前节点高度是否满足平衡二叉树,若满足,则判定节点的子节点。

    2.自底向上:

    在方法一中,计算节点的高度是消耗时间资源的,因此可以采用自底向上的方法。

    对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。

    实现

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    1.
    class Solution:
        def isBalanced(self, root: TreeNode) -> bool:
            def level(node: TreeNode):
                if not node:
                    return 0
                else:
                    return max(level(node.left), level(node.right)) + 1
                
            if not root:
                return True
            return abs(level(root.left) - level(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
    
    2.
    class Solution:
        def isBalanced(self, root: TreeNode) -> bool:
            def height(root: TreeNode) -> int:
                if not root:
                    return 0
                leftHeight = height(root.left)
                rightHeight = height(root.right)
                if leftHeight == -1 or rightHeight == -1 or abs(leftHeight - rightHeight) > 1:
                    return -1
                else:
                    return max(leftHeight, rightHeight) + 1
    
            return height(root) >= 0

    题目111

    二叉树的最小深度

    给定一个二叉树,找出其最小深度。

    最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

    说明: 叶子节点是指没有子节点的节点。

    示例:

    给定二叉树 [3,9,20,null,null,15,7],

         3
        /
      9   20
          /   
        15     7
    返回它的最小深度  2.

    思路

    当左孩子和右孩子都为空的情况,说明到达了叶子节点,直接返回1即可

    当左孩子和由孩子其中一个为空,那么需要返回比较大的那个孩子的深度

    当左右孩子都不为空,返回最小深度+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 minDepth(self, root: TreeNode) -> int:
            if not root:
                return 0
            if not root.left and not root.right:
                return 1
            l = self.minDepth(root.left)
            r = self.minDepth(root.right)
            if not root.left or not root.right:
                return l + r + 1
            return min(l,r)+1

    题目112

    路径总和

    给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

    说明: 叶子节点是指没有子节点的节点。

    示例: 
    给定如下二叉树,以及目标和 sum = 22,

            5
           /
         4    8
        /     /
      11     13  4
    /            
    7    2           1

    思路

    递归:若当前节点就是叶子节点,那么我们直接判断 sum 是否等于 val,若不是叶子节点则继续

    实现

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def hasPathSum(self, root: TreeNode, sum: int) -> bool:
            if not root:
                return False
            if not root.left and not root.right:
                return sum == root.val
            sum -= root.val
            return self.hasPathSum(root.left, sum) or self.hasPathSum(root.right, sum)

    题目113

    路径总和II

    给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

    说明: 叶子节点是指没有子节点的节点。

    示例:
    给定如下二叉树,以及目标和 sum = 22,

             5
           /
         4    8
        /     /
      11     13  4
    /            
    7    2           1

    返回:

    [ [5,4,11,2], [5,8,4,5] ]

    思路

    与上一题完全一致

    实现

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
            result = []
            def hasPathSum(root: TreeNode, sum: int, res):
                if not root:
                    return
                if not root.left and not root.right:
                    if sum == root.val:
                        result.append(res+[root.val])
                sum -= root.val
                hasPathSum(root.left, sum, res+[root.val])
                hasPathSum(root.right, sum, res+[root.val])
            hasPathSum(root,sum,[])
            return result

    题目114

    给定一个二叉树,原地将它展开为一个单链表。

    例如,给定二叉树

        1
       /
      2   5
     /    
    3   4    6  
    将其展开为:

    1
     
      2
       
         3
         
           4
             
              5
               
                6

    思路

    1.前序遍历:前序遍历后放入数组中,再重新组合

    2.寻找前驱节点:

    实现

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, val=0, left=None, right=None):
    #         self.val = val
    #         self.left = left
    #         self.right = right
    1.
    class Solution:
        def flatten(self, root: TreeNode) -> None:
            """
            Do not return anything, modify root in-place instead.
            """
            def preorder(node,lis):
                if not node:
                    return
                lis.append(node)
                preorder(node.left,lis)
                preorder(node.right,lis)
            res = []
            preorder(root, res)
            size = len(res)
            for i in range(1, size):
                prev, curr = res[i - 1], res[i]
                prev.left = None
                prev.right = curr
    2.
    class Solution:
        def flatten(self, root: TreeNode) -> None:
            """
            Do not return anything, modify root in-place instead.
            """

            curr = root
            while curr:
                if curr.left:
                    pre = next = curr.left
                    while pre.right:
                        pre = pre.right
                    pre.right = curr.right
                    curr.left = None
                    curr.right = next
                curr = curr.right


    题目116

    填充每个节点的下一个右侧节点指针

    给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。

    填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

    初始状态下,所有 next 指针都被设置为 NULL。

    思路

    广度优先遍历:利用广度优先遍历,将每一层的节点都放入队列中,对同一层的元素来进行连接

    实现

    """
    # Definition for a Node.
    class Node:
        def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
            self.val = val
            self.left = left
            self.right = right
            self.next = next
    """
    from collections import deque
    
    class Solution:
        def connect(self, root: 'Node') -> 'Node':
            if not root:
                return None
            queue = deque([root])
            while queue:
                size = len(queue)
                for i in range(size):
                    node = queue.popleft()
                    if i < size -1:
                        node.next = queue[0]
                    if node.left:
                        queue.append(node.left)
                    if node.right:
                        queue.append(node.right)
            return root

    题目116 

    填充每个节点的下一个右侧节点指针II

    给定一个二叉树。

    填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

    初始状态下,所有 next 指针都被设置为 NULL。

    思路

     与上题思路完全一致

    实现

    """
    # Definition for a Node.
    class Node:
        def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
            self.val = val
            self.left = left
            self.right = right
            self.next = next
    """
    from collections import deque
    class Solution:
        def connect(self, root: 'Node') -> 'Node':
            if not root:
                return None
            queue = deque([root])
            while queue:
                size = len(queue)
                for i in range(size):
                    node = queue.popleft()
                    if i < size -1:
                        node.next = queue[0]
                    if node.left:
                        queue.append(node.left)
                    if node.right:
                        queue.append(node.right)
            return root

    题目118

    杨辉三角

    给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。

    思路

    递归法

    实现

    class Solution:
        def generate(self, numRows: int) -> List[List[int]]:
            res = []
            def ge(numRows):
                if numRows == 1:
                    res.append([1])
                    return [1]
                else:
                    up = [0]+ ge(numRows-1) + [0]
                    tmp = []
                    for i in range(len(up)-1):
                        val = up[i] + up[i+1]
                        tmp.append(val)
                    res.append(tmp)
                    return tmp
            if numRows == 0:
                return []
            ge(numRows)
            return res

    题目119

    杨辉三角II

    给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 行。

    思路

    递归法

    实现

    class Solution:
        def getRow(self, rowIndex: int) -> List[int]:
            def ge(numRows):
                if numRows == 0:
                    return [1]
                else:
                    up = [0]+ ge(numRows-1) + [0]
                    tmp = []
                    for i in range(len(up)-1):
                        val = up[i] + up[i+1]
                        tmp.append(val)
                    return tmp
            return ge(rowIndex)

    题目120

    三角形最小路径和

    给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。

    相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。

    例如,给定三角形:

    [
    [2],
    [3,4],
    [6,5,7],
    [4,1,8,3]
    ]
    自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

    思路

    1.递归:遍历所有点,但效率太低

    2.动态规划

    实现

    class Solution:
        def minimumTotal(self, triangle: List[List[int]]) -> int:
            triangle_len = len(triangle)
            result = [0 for i in range(triangle_len)]
            for i in range(0, triangle_len):
                before = result[:]          
                for j in range(1, i):
                    temp = before[j-1:j+1]
                    result[j] = min(temp) + triangle[i][j]
                if i != 0:
                    result[i] = triangle[i][i] + before[i-1]
                result[0] += triangle[i][0]
            return min(result)

    题目121

    买卖股票的最佳时机

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

    如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

    注意:你不能在买入股票前卖出股票。 

    示例 1:

    输入: [7,1,5,3,6,4]
    输出: 5
    解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
    注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

    思路

    对于当前天数,最大利润为当天的价格减去之前的最低价格

    实现

    class Solution:
        def maxProfit(self, prices: List[int]) -> int:
            days = len(prices)
            minprice = int(1e9)
            max_profit = 0
            for day in range(days):
                if prices[day] < minprice:
                    minprice = prices[day]
                cur_profit = prices[day] - minprice
                if cur_profit > max_profit:
                    max_profit = cur_profit
            return max_profit

    题目122

    买卖股票的最佳时机2

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

    设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

    注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

    示例 1:

    输入: [7,1,5,3,6,4]
    输出: 7
    解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
    随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

    思路

    遍历一次数组,当当前元素小于后一个元素时,则可以获得利润差

    实现

    class Solution:
        def maxProfit(self, prices: List[int]) -> int:
            days = len(prices)
            profit = 0
            for day in range(days-1):
                if prices[day] < prices[day + 1]:
                    profit += (prices[day + 1] - prices[day])
            return profit

    题目125

    验证回文串

    给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

    说明:本题中,我们将空字符串定义为有效的回文串。

    示例 1:

    输入: "A man, a plan, a canal: Panama"
    输出: true

    思路

    实现

    class Solution:
        def isPalindrome(self, s: str) -> bool:
            strlen = len(s)
            s = s.upper()
            left = 0
            right = strlen -1
            while left < right:
                print(s[left],"+",s[right])
                if not s[left].isalnum():
                    left += 1
                    continue
                elif not s[right].isalnum():
                    right -= 1
                    continue
                elif s[left] != s[right]:
                    return False
                left += 1
                right -= 1
            return True
                

    题目127

    单词接龙

    给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:

    每次转换只能改变一个字母。
    转换过程中的中间单词必须是字典中的单词。
    说明:

    如果不存在这样的转换序列,返回 0。
    所有单词具有相同的长度。
    所有单词只由小写字母组成。
    字典中不存在重复的单词。
    你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
    示例 1:

    输入:
    beginWord = "hit",
    endWord = "cog",
    wordList = ["hot","dot","dog","lot","log","cog"]

    输出: 5

    思路

    广度优先算法

    实现

    class Solution(object):
        def ladderLength(self, beginWord, endWord, wordList):
            """
            :type beginWord: str
            :type endWord: str
            :type wordList: List[str]
            :rtype: int
            """
            wordList=set(wordList)
            q=[(beginWord,1)]
            if endWord not in wordList:
                return 0
            while q:
                node,level=q.pop(0)
                if node == endWord:
                    return level
                for i in range(len(node)):
                    for j in "abcdefghijklmnopqrstuvwxyz":
                        new=node[:i]+j+node[i+1:]
                        if new in wordList:
                            q.append((new,level+1))
                            wordList.remove(new)
            return 0

    题目129

    求根到叶子节点数字之和

    给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。

    例如,从根到叶子节点路径 1->2->3 代表数字 123。

    计算从根到叶子节点生成的所有数字之和。

    说明: 叶子节点是指没有子节点的节点。

    示例 1:

    输入: [1,2,3]
      1
     /
    2  3 
    输出: 25
    解释:
    从根到叶子节点路径 1->2 代表数字 12.
    从根到叶子节点路径 1->3 代表数字 13.
    因此,数字总和 = 12 + 13 = 25.

    思路

    深度优先遍历

    实现

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def sumNumbers(self, root: TreeNode) -> int:
    
            def dfs(node,cur_sum):
                if not node:
                    return 0
                temp = cur_sum*10 + node.val
                if not node.left and not node.right:
                    return temp
                else:
                    return dfs(node.left, temp) + dfs(node.right,temp)
            return dfs(root,0)
                

    题目130

    被围绕的区域

    给定一个二维的矩阵,包含 'X' 和 'O'(字母 O)。

    找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。

    示例:

    X X X X
    X O O X
    X X O X
    X O X X
    运行你的函数后,矩阵变为:

    X X X X
    X X X X
    X X X X
    X O X X

    思路

    首先对元素进行分类:1.X 2.被包围的O 3.没有被包围的O

    此题可以发现在四周边上的O都是不被包围的,因此可以对这些边上的O做深度优先遍历获取所有与其连接的O

    实现

    class Solution:
        def solve(self, board: List[List[str]]) -> None:
            """
            Do not return anything, modify board in-place instead.
            """
            if not board:
                return
            row = len(board)
            col = len(board[0])
            visited = [[False for _ in range(row)] for _ in range(col)]
            def dfs(i,j):
                if 0 <= i < row and 0 <= j < col:
                    if board[i][j] != 'O':
                        return
                    else:
                        board[i][j] = 'A'
                        dfs(i+1,j)
                        dfs(i-1,j)
                        dfs(i,j+1)
                        dfs(i,j-1)
            for i in range(row):
                dfs(i,0)
                dfs(i,col-1)
            for j in range(col):
                dfs(0,j)
                dfs(row-1, j)
    
            for i in range(row):
                for j in range(col):
                    if board[i][j] == "A":
                        board[i][j] = "O"
                    elif board[i][j] == "O":
                        board[i][j] = "X"
  • 相关阅读:
    1021. 从前有座山——java
    1004. 西西弗斯式的命运——java
    1025. 水枪灭火——java
    1020. 分解质因数——java
    1024.排序——C语言
    1024. 排序——java
    1022. Fib数列——java
    1006. 求和游戏——java
    1005. 数独——java
    SpringBoot 升级到 2.1 后,启动程序时控制台不打印 API 的解决方法及一些感想
  • 原文地址:https://www.cnblogs.com/mgdzy/p/13667948.html
Copyright © 2020-2023  润新知