leetcode-剑指offer

本文涵盖了数组操作、链表处理、树与图算法、搜索与排序、动态规划、字符串处理、数据结构优化、复杂问题解决等多种IT核心主题,带你深入理解并解决实际编程问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

03. 数组中的重复数字

04. 二维数组的查找

05. 替换空格

06. 从尾到头打印链表

07. 重建二叉树

09. 用两个栈实现队列

10-I. 斐波那契数列

10-II. 青蛙跳台阶问题

11. 旋转数组的最小数字

12. 矩阵中的路径

13. 机器人的运动范围

14-I. 剪绳子

14-II. 剪绳子

15. 二进制中1的个数

16. 数值的整数次方

17. 打印从1到最大的n

18. 删除链表的节点

19. 正则表达式匹配 

20. 表示数值的字符串

21. 调整数组顺序使奇数位于偶数前面

22. 链表中倒数第k个节点

24. 反转链表

25. 合并两个排序的链表

26. 树的子结构

27. 二叉树的镜像 

28. 对称的二叉树

29. 顺时针打印矩阵

30. 包含Min函数的栈

31. 栈的压入、弹出序列

32-I. 从上到下打印二叉树

32-II. 从上到下打印二叉树

32-III. 从上到下打印二叉树

33. 二叉搜索树的后序遍历

34. 二叉树中和为某一值的路径

35. 复杂链表的复制

36. 二叉搜索树与双向链表

37. 序列化二叉树

38. 字符串的排列

39. 数组中出现次数超过一半的数

40. 最小的k个数

41. 数据流中的中位数

42. 连续子数组的最大和

43. 1~n整数中1出现的次数

44. 数字序列中某一位的数字

45. 把数组排成最小的数 

46. 把数字翻译成字符串 

47. 礼物的最大价值 

48. 最长不含重复字符的子字符串

49. 丑数

50. 第一个只出现一次的字符

51. 数组中的逆序对

52. 两个链表的第一个公共节点

53-I. 在排序数组中查找数字

53-II. 0~n-1中缺失的数字

54. 二叉搜索树第K大节点 

55-I. 二叉树的深度

55-II. 平衡二叉树

56-I. 数组中数字出现的次数

56-II. 数组中数字出现的次数

57-I. 和为s的两个数字

57-II. 和为s的连续正数序列

58-I. 反转单词顺序

58-II. 左旋转字符串

59-I. 滑动窗口的最大值

59-II. 队列的最大值

60. n个骰子的点数

61. 扑克牌中的顺子

62. 圆圈中最后剩下的数字(约瑟夫环)

63. 股票的最大利润

64. 求1+2+...+n

65. 不用加减乘除做加法

66. 构建乘积数组

67. 把字符串转换成整数

68-I. 二叉搜索树最近的公共祖先

68-II. 二叉树最近的公共祖先


03. 数组中的重复数字

class Solution(object):
    def findRepeatNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        for i in range(1, len(nums)):
            if nums[i] == nums[i-1]:
                return nums[i]

04. 二维数组的查找

class Solution(object):
    def findNumberIn2DArray(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        n = len(matrix)  # 行
        if not n:
            return False
        m = len(matrix[0])  # 列
        if not m:
            return False
        row = set(i for i in range(n))
        col = set(i for i in range(m))
        for i in range(n):
            if matrix[i][0] == target or matrix[i][m-1] == target:
                return True
            elif matrix[i][0] > target or matrix[i][m-1] < target:
                row.remove(i)
        for j in range(m):
            if matrix[0][j] == target or matrix[n-1][j] == target:
                return True
            elif matrix[0][j] > target or matrix[n-1][j] < target:
                col.remove(j)
        for i in row:
            for j in col:
                if matrix[i][j] == target:
                    return True
        return False

 也即“线性搜索”的思路,从matrix右上角开始搜索,如果targrt更小则向左搜索,targrt更大则向下搜索:

class Solution(object):
    def findNumberIn2DArray(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        i, j = len(matrix) - 1, 0
        while i >= 0 and j < len(matrix[0]):
            if matrix[i][j] > target: i -= 1
            elif matrix[i][j] < target: j += 1
            else: return True
        return False

05. 替换空格

 可以直接用replace函数

class Solution(object):
    def replaceSpace(self, s):
        """
        :type s: str
        :rtype: str
        """
        ss = s.replace(' ', '%20')
        return ss
class Solution:
    def replaceSpace(self, s):
        res = []
        for c in s:
            if c == ' ': 
                res.append("%20")
            else: res.append(c)
        return "".join(res)

06. 从尾到头打印链表

 

class Solution:
    def reversePrint(self, head: ListNode):
        return self.reversePrint(head.next) + [head.val] if head else []

class Solution:
    def reversePrint(self, head: ListNode):
        stack = []
        while head:
            stack.append(head.val)
            head = head.next
        return stack[::-1]

这两种方法都比暴力解法慢,可能因为是简单题吧

class Solution(object):
    def reversePrint(self, head):
        """
        :type head: ListNode
        :rtype: List[int]
        """
        head_li = []
        while head:
            head_li.append(head.val)
            head = head.next
        ans = []
        while head_li:
            tmp = head_li.pop()
            ans.append(tmp)
        return ans

07. 重建二叉树

 

class Solution(object):
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        def recur(root, left, right):
            """
            :param root: 根节点在前序遍历的索引
            :param left: 子树在中序遍历的左边界
            :param right: 子树在中序遍历的右边界
            :return: 根节点
            """
            # 递归终止
            if left > right: return
            # 建立根节点
            node = TreeNode(preorder[root])
            # 找到根节点在中序遍历的索引i
            # 划分根节点、左子树、右子树
            i = dic[preorder[root]]
            # 开启左子树递归
            node.left = recur(root + 1, left, i - 1)
            # 开启右子树递归
            node.right = recur(i - left + root + 1, i + 1, right)
            # 回溯返回根节点
            return node

        # dic[key] = value,key为中序遍历中的值,i为中序遍历的下标
        # 通过dic[node]可以获得node在中序遍历中对应的下标
        dic = {}
        for i in range(len(inorder)):
            dic[inorder[i]] = i
        return recur(0, 0, len(inorder) - 1)

09. 用两个栈实现队列

class CQueue:
    def __init__(self):
        self.A, self.B = [], []

    def appendTail(self, value: int):
        self.A.append(value)

    def deleteHead(self):
        if self.B: return self.B.pop()
        if not self.A: return -1
        while self.A:
            self.B.append(self.A.pop())
        return self.B.pop()

10-I. 斐波那契数列

 方法一:动态规划

class Solution(object):
    def fib(self, n):
        """
        :type n: int
        :rtype: int
        """
        MOD = 10 ** 9 + 7
        if n < 2:
            return n
        p, q, r = 0, 0, 1
        for i in range(2, n + 1):
            p = q
            q = r
            r = (p + q) % MOD
        return r

方法二:矩阵快速幂

class Solution(object):
    def fib(self, n):
        """
        :type n: int
        :rtype: int
        """
        MOD = 10 ** 9 + 7
        if n < 2:
            return n

        def multiply(a, b):
            c = [[0, 0], [0, 0]]
            for i in range(2):
                for j in range(2):
                    c[i][j] = (a[i][0] * b[0][j] + a[i][1] * b[1][j]) % MOD
            return c

        def matrix_pow(a, n):
            ret = [[1, 0], [0, 1]]
            while n > 0:
                if n & 1:
                    ret = multiply(ret, a)
                n >>= 1
                a = multiply(a, a)
            return ret

        res = matrix_pow([[1, 1], [1, 0]], n - 1)
        return res[0][0]

10-II. 青蛙跳台阶问题

class Solution(object):
    def numWays(self, n):
        """
        :type n: int
        :rtype: int
        """
        a, b = 1, 1
        for _ in range(n):
            a, b = b, a + b
        return a % 1000000007

11. 旋转数组的最小数字

class Solution(object):
    def minArray(self, numbers):
        """
        :type numbers: List[int]
        :rtype: int
        """
        left, right = 0, len(numbers) - 1
        while left < right:
            mid = (left + right) // 2
            if numbers[mid] > numbers[right]:
                left = mid + 1
            elif numbers[mid] < numbers[right]:
                right = mid
            else:
                right -= 1
        return numbers[left]

12. 矩阵中的路径

class Solution(object):
    def exist(self, board, word):
        """
        :type board: List[List[str]]
        :type word: str
        :rtype: bool
        """
        dirs = [(0, 1), (0, -1), (1, 0), (-1, 0)]

        # 从board的(i,j)位置出发是否能搜索到单词,begin代表word从第begin个字符开始的后缀子串
        def check(cur_row, cur_col, begin):
            if board[cur_row][cur_col] != word[begin]:  # 判断首字母是否匹配
                return False
            if begin == len(word) - 1:  # 判断到最后一个返回True
                return True
            visited.add((cur_row, cur_col))  # 存储走过的路径
            result = False
            for dx, dy in dirs:
                next_row, next_col = cur_row + dx, cur_col + dy
                if 0 <= next_row < len(board) and 0 <= next_col < len(board[0]) \
                        and (next_row, next_col) not in visited:
                    if check(next_row, next_col, begin + 1):
                        result = True
                        break
            # 如果没有return True说明这条路径是不对的,返回上一层
            visited.remove((cur_row, cur_col))
            return result

        n_row, n_col = len(board), len(board[0])
        visited = set()
        for i in range(n_row):
            for j in range(n_col):
                if check(i, j, 0):
                    return True

        return False

13. 机器人的运动范围

class Solution(object):
    def movingCount(self, m, n, k):
        """
        :type m: int
        :type n: int
        :type k: int
        :rtype: int
        """
        dirs = {(0,1),(1,0),(0,-1),(-1,0)}

        def sumindex(num):
            ans = 0
            while num != 0:
                ans += num % 10
                num = num // 10
            return ans

        def dfs(cur_row, cur_col):
            for dir in dirs:
                next_row = cur_row + dir[0]
                next_col = cur_col + dir[1]
                if -1 < next_row < m and -1 < next_col < n \
                        and (next_row, next_col) not in visited \
                        and sumindex(next_row) + sumindex(next_col) <= k:
                    visited.add((next_row, next_col))
                    dfs(next_row, next_col)

        visited = set()
        visited.add((0,0))
        dfs(0, 0)
        return len(visited)

14-I. 剪绳子

 推论1:将绳子以相等的长度等分为多段,得到的乘积最大

推论2:尽可能将绳子以长度3等分为多段,乘积最大

思路:先按照长度3分段,余数为1则把3+1替换为2+2,余数为2则直接乘上去

class Solution(object):
    def cuttingRope(self, n):
        """
        :type n: int
        :rtype: int
        """
        # 绳子长度为2时最大乘积为1,为3时最大乘积为2
        if n <= 3: return n - 1
        a, b = n // 3, n % 3
        if b == 0: return int(math.pow(3, a))
        if b == 1: return int(math.pow(3, a - 1) * 4)
        return int(math.pow(3, a) * 2)

math.pow速度更快

14-II. 剪绳子

15. 二进制中1的个数

 右移一位的时候二进制数格式中的最后一位直接消失

n&1在n为四位二进制数的情况下相当于n&0001,所以只有最右一位有效

res = 0
while n:
    res += n & 1
    n >>= 1
return res

res = 0
while n:
    res += 1
    n &= n - 1
return res

16. 数值的整数次方

class Solution(object):
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        # 特殊情况讨论
        if x == 0: 
            return 0
        if n < 0: 
            x, n = 1 / x, -n
        ans = 1
        # 当n二进制数最右一位为1,ans+=x
        while n:
            if n & 1:
                ans *= x
            x *= x
            n >>= 1
        return ans

17. 打印从1到最大的n

class Solution(object):
    def printNumbers(self, n):
        """
        :type n: int
        :rtype: List[int]
        """
        # x:当前应固定从右到左第x位
        def dfs(x):
            # 终止条件:已固定完所有位
            if x == n:
                # 拼接 num 并添加至 res 尾部,并去除开始的0(无意义0)
                s = ''.join(num[self.start:])
                res.append(int(s))
                # 进位
                if n - self.start == self.nine: self.start -= 1
                return
            # 遍历 0 - 9
            for i in range(10):
                if i == 9: self.nine += 1
                num[x] = str(i)  # 固定第 x 位为 i
                dfs(x + 1)  # 开启固定第 x + 1 位
            self.nine -= 1  # 进位以后少一个9

        # num存储当前数字
        # res存储所有结果
        num, res = ['0'] * n, []
        self.nine = 0  # 标记数字中9的数量
        self.start = n - 1  # 标记数字中第一个非0位
        dfs(0)
        return res[1:]

18. 删除链表的节点

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def deleteNode(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        if head.val == val:
            return head.next
        pre, cur = head, head.next
        # 定位节点
        while cur and cur.val != val:
            pre, cur = cur, cur.next
        # 修改引用
        pre.next = cur.next
        return head

19. 正则表达式匹配 

class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        m = len(s)
        n = len(p)
        # dp[0][0]代表空字符状态
        # dp[i][j]标记s[:i+1]与p[:j+1]是否匹配
        dp = [[0 for _ in range(n+1)] for _ in range(m+1)]
        dp[0][0] = 1  # 空字符匹配
        # 初始化:首行中只有p的奇数位为*时匹配(只看dp第一行偶数位)
        for j in range(2, n+1, 2):
            if p[j-1] == '*':
                dp[0][j] = dp[0][j-2]
        # 填充状态转移矩阵
        for i in range(1, m+1):
            for j in range(n+1):
                if p[j-1] == '*':
                    # 多一个p中字符
                    # 匹配p[j-2]字符零次的情况,判断s[:i+1]与p[:j-1]
                    if j > 1 and dp[i][j-2]:
                        dp[i][j] = 1
                    # 多一个s中字符
                    # 匹配p[j-2]字符,判断多的s字符与p[j-2]是否匹配
                    if j > 1 and dp[i-1][j] and s[i-1] == p[j-2]:
                        dp[i][j] = 1
                    if j > 1 and dp[i-1][j] and p[j-2] == '.':
                        dp[i][j] = 1
                else:
                    # s/p同时多一个字符
                    if j > 0 and dp[i-1][j-1] and s[i-1] == p[j-1]:
                        dp[i][j] = 1
                    if j > 0 and dp[i-1][j-1] and p[j-1] == '.':
                        dp[i][j] = 1
        return dp[m][n]

20. 表示数值的字符串

21. 调整数组顺序使奇数位于偶数前面

class Solution(object):
    def exchange(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        left = 0
        right = len(nums) - 1
        while left < right:
            if nums[left] % 2:
                left += 1
            else:
                while right > left and not nums[right] % 2:
                    right -= 1
                nums[left], nums[right] = nums[right], nums[left]
                left += 1
                right -= 1
        return nums

x &1 位运算 等价于 x % 2 取余运算,即皆可用于判断数字奇偶性。写法更加简洁:

class Solution(object):
    def exchange(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        left, right = 0, len(nums) - 1
        while left < right:
            while left < right and nums[left] & 1 == 1:
                left += 1
            while left < right and nums[right] & 1 == 0:
                right -= 1
            nums[left], nums[right] = nums[right], nums[left]
        return nums

22. 链表中倒数第k个节点

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getKthFromEnd(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        count = 1
        node = head
        while node.next:
            count += 1
            node = node.next
        i = count - k
        while i > 0:
            head = head.next
            i -= 1
        return head

另一种方法采用快慢指针:

class Solution(object):
    def getKthFromEnd(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        fast, slow = head, head
        while fast and k > 0:
            fast, k = fast.next, k - 1
        while fast:
            fast,slow = fast.next,slow.next
        return slow

24. 反转链表

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        cur, pre = head, None
        while cur:
            tmp = cur.next # 暂存后继节点 cur.next
            cur.next = pre # 修改 next 引用指向
            pre = cur      # pre 暂存 cur
            cur = tmp      # cur 访问下一节点
        return pre

或者按照下图思路方便理解:

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        cur, pre = None, head
        if not head:
            return None
        while pre.next:
            tmp = pre.next
            pre.next = cur
            cur = pre
            pre = tmp
        pre.next = cur
        return pre

25. 合并两个排序的链表

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        head = ListNode(0)
        pre = head
        while l1 and l2:
            if l1.val <= l2.val:
                pre.next = l1
                pre = pre.next
                l1 = l1.next
            else:
                pre.next = l2
                pre = pre.next
                l2 = l2.next
        pre.next = l1 if l1 else l2
        return head.next

Python三元表达式写法A if x else B,代表当 x = True 时执行A,否则执行B。

26. 树的子结构

 

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

class Solution(object):
    def isSubStructure(self, A, B):
        """
        :type A: TreeNode
        :type B: TreeNode
        :rtype: bool
        """
        def recur(A, B):
            # B节点为空,已经遍历完成,返回True
            if not B: 
                return True
            # A节点为空/AB节点值不同,返回False
            if not A or A.val != B.val: return False
            # 继续遍历AB的左子节点/右子节点
            return recur(A.left, B.left) and recur(A.right, B.right)
        # 如果AB不为空,且
        # 以A为根节点的子树包含B
        # /以A的左孩子为根节点的子树包含B
        # /以A的右孩子为根节点的子树包含B
        return bool(A and B) and (recur(A, B) 
                                  or self.isSubStructure(A.left, B) 
                                  or self.isSubStructure(A.right, B))

迭代/BFS(广度优先搜索):

class Solution:
    def isSubStructure(self, A, B):
        # 判断AB结构是否相同
        def helper(A, B):
            queue = [(A, B)]
            while queue:
                nodeA, nodeB = queue.pop(0)
                if not nodeA or nodeA.val != nodeB.val:
                    return False
                if nodeB.left:
                    queue.append((nodeA.left, nodeB.left))
                if nodeB.right:
                    queue.append((nodeA.right, nodeB.right))
            return True

        if not B: return False
        queue = collections.deque([A])
        # 找A中与B根节点值相同的node
        while queue:
            node = queue.popleft()
            if node.val == B.val:
                if helper(node, B):
                    return True
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        return False

递归/DFS(深度优先搜索):用时最少

class Solution:
    def isSubStructure(self, A, B):
        if not B: return False

        def dfs(nodeA):
            if not nodeA: return False
            if nodeA.val == B.val:
                if self.helper(nodeA, B):
                    return True
            return dfs(nodeA.left) or dfs(nodeA.right)

        return dfs(A)

    def helper(self, nodeA, nodeB):
        if not nodeB:
            return True
        if not nodeA or nodeA.val != nodeB.val:
            return False
        return self.helper(nodeA.left, nodeB.left) \
               and self.helper(nodeA.right, nodeB.right)

27. 二叉树的镜像 

 递归/DFS(深度优先搜索)

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

class Solution(object):
    def mirrorTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return root
        left = self.mirrorTree(root.left)
        right = self.mirrorTree(root.right)
        root.left, root.right = right, left
        return root

辅助栈(和32.从上到下打印二叉树类似的解法)

class Solution(object):
    def mirrorTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root: return
        stack = [root]
        while stack:
            node = stack.pop()
            if node.left: stack.append(node.left)
            if node.right: stack.append(node.right)
            node.left, node.right = node.right, node.left
        return root

28. 对称的二叉树

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

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        def recur(L, R):
            if not L and not R: return True
            if not L or not R or L.val != R.val: return False
            return recur(L.left, R.right) and recur(L.right, R.left)

        return recur(root.left, root.right) if root else True

29. 顺时针打印矩阵

# 暴力解法
class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        if not matrix: return []
        row = len(matrix)
        col = len(matrix[0])
        dirs = [(0,1),(1,0),(0,-1),(-1,0)]
        dirv = 0
        dp = [[0 for _ in range(col)] for _ in range(row)]
        dp[0][0] = 1
        ans = [matrix[0][0]]

        # 从第i行第j列开始
        def dfs(x, y, dirv):
            if (x == 0 or dp[x-1][y] == 1) and (x == row-1 or dp[x+1][y] == 1) \
                    and (y == 0 or dp[x][y-1] == 1) and (y == col-1 or dp[x][y+1] == 1):
                return ans
            if dirv == 0 and (y == col-1 or dp[x][y+1] == 1):
                dirv = 1
            elif dirv == 1 and (x == row - 1 or dp[x+1][y] == 1):
                dirv = 2
            elif dirv == 2 and (y == 0 or dp[x][y-1] == 1):
                dirv = 3
            elif dirv == 3 and (x == 0 or dp[x-1][y] == 1):
                dirv = 0
            next_x = x + dirs[dirv][0]
            next_y = y + dirs[dirv][1]
            ans.append(matrix[next_x][next_y])
            dp[next_x][next_y] = 1
            dfs(next_x, next_y,dirv)

        dfs(0,0,dirv)
        return ans
# 优秀解法
class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        if not matrix: return []
        l, r, t, b, ans = 0, len(matrix[0]) - 1, 0, len(matrix) - 1, []
        while True:
            # left to right
            for i in range(l, r + 1):
                ans.append(matrix[t][i])
            t += 1
            if t > b: break
            # top to bottom
            for i in range(t, b + 1):
                ans.append(matrix[i][r])
            r -= 1
            if l > r: break
            # right to left
            for i in range(r, l - 1, -1):
                ans.append(matrix[b][i])
            b -= 1
            if t > b: break
            # bottom to top
            for i in range(b, t - 1, -1): 
                ans.append(matrix[i][l])
            l += 1
            if l > r: break
        return ans

30. 包含Min函数的栈

class MinStack:
    def __init__(self):
        self.A, self.B = [], []

    def push(self, x: int):
        self.A.append(x)
        if not self.B or self.B[-1] >= x:
            self.B.append(x)

    def pop(self):
        if self.A.pop() == self.B[-1]:
            self.B.pop()

    def top(self):
        return self.A[-1]

    def min(self):
        return self.B[-1]

# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()

31. 栈的压入、弹出序列

class Solution(object):
    def validateStackSequences(self, pushed, popped):
        """
        :type pushed: List[int]
        :type popped: List[int]
        :rtype: bool
        """
        stack = []
        k = 0
        for num in pushed:
            stack.append(num)
            while stack and stack[-1] == popped[k]:
                stack.pop()
                k += 1
        if not stack:
            return True
        return False

32-I. 从上到下打印二叉树

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

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if not root: return []
        res, queue = [], collections.deque()
        queue.append(root)
        while queue:
            node = queue.popleft()
            res.append(node.val)
            if node.left: queue.append(node.left)
            if node.right: queue.append(node.right)
        return res

32-II. 从上到下打印二叉树

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

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root: return []
        res, queue = [], collections.deque()
        queue.append(root)
        while queue:
            tmp = []
            for _ in range(len(queue)):
                node = queue.popleft()
                tmp.append(node.val)
                if node.left: queue.append(node.left)
                if node.right: queue.append(node.right)
            res.append(tmp)
        return res

32-III. 从上到下打印二叉树

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

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root: return []
        res, deque = [], collections.deque([root])
        while deque:
            tmp = collections.deque()
            for _ in range(len(deque)):
                node = deque.popleft()
                if len(res) % 2: tmp.appendleft(node.val) # 偶数层 -> 队列头部
                else: tmp.append(node.val) # 奇数层 -> 队列尾部
                if node.left: deque.append(node.left)
                if node.right: deque.append(node.right)
            res.append(list(tmp))
        return res

33. 二叉搜索树的后序遍历

class Solution(object):
    def verifyPostorder(self, postorder):
        """
        :type postorder: List[int]
        :rtype: bool
        """
        n = len(postorder)

        def recur(i, j):
            if i >= j: return True
            root = j
            # 找到右子树的第一个元素
            p = i
            while postorder[p] < postorder[root]: p += 1
            right = p
            # 找到右子树最后一个元素
            while postorder[p] > postorder[root]: p += 1
            return p == root and recur(i, right-1) and recur(right, j-1)

        return recur(0,n-1)

34. 二叉树中和为某一值的路径

 DFS

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

class Solution(object):
    def pathSum(self, root, target):
        """
        :type root: TreeNode
        :type target: int
        :rtype: List[List[int]]
        """
        def dfs(cur, curtarget, path, res):
            if not cur.left and not cur.right:
                if curtarget == 0:
                    res.append(path)
                    return
                return
            if cur.val != curtarget and not cur.right and not cur.left:
                return
            if cur.left:
                dfs(cur.left, curtarget - cur.left.val, path + [cur.left.val], res)
            if cur.right:
                dfs(cur.right, curtarget - cur.right.val, path + [cur.right.val], res)

        if not root: return []
        path = [root.val]
        res = []
        dfs(root, target - root.val, path, res)
        return res

看这种方法不需要那么多的传递参数:

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


class Solution(object):
    def pathSum(self, root, target):
        """
        :type root: TreeNode
        :type target: int
        :rtype: List[List[int]]
        """
        res = list()
        path = list()

        def dfs(root, target):
            if not root:
                return
            path.append(root.val)
            target -= root.val
            if not root.left and not root.right and target == 0:
                res.append(path[:])
                # path[:]的作用好像是返回当前path,不会随着后面path变化而改变
            dfs(root.left, target)
            dfs(root.right, target)
            path.pop()

        dfs(root, target)
        return res

BFS:使用哈希表记录树中的每一个节点的父节点。每次找到一个满足条件的节点,我们就从该节点出发不断向父节点迭代,即可还原出从根节点到当前节点的路径。

import collections


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


class Solution(object):
    def pathSum(self, root, target):
        """
        :type root: TreeNode
        :type target: int
        :rtype: List[List[int]]
        """
        res = list()
        # 调用parent中不存在的key时返回None
        parent = collections.defaultdict(lambda: None)

        def getPath(node):
            tmp = list()
            while node:
                tmp.append(node.val)
                node = parent[node]
            res.append(tmp[::-1])

        if not root: return res

        que_node = collections.deque([root])
        que_total = collections.deque([0])

        while que_node:
            node = que_node.popleft()
            rec = que_total.popleft() + node.val

            if not node.left and not node.right:
                if rec == target:
                    getPath(node)
            else:
                if node.left:
                    parent[node.left] = node
                    que_node.append(node.left)
                    que_total.append(rec)
                if node.right:
                    parent[node.right] = node
                    que_node.append(node.right)
                    que_total.append(rec)

        return res

35. 复杂链表的复制

"""
# Definition for a Node.
class Node:
    def __init__(self, x, next=None, random=None):
        self.val = int(x)
        self.next = next
        self.random = random
"""
class Solution(object):
    def copyRandomList(self, head):
        """
        :type head: Node
        :rtype: Node
        """
        if not head:
            return None
        # 第一步,在每个原节点后面创建一个新节点
        # 1->1'->2->2'->3->3'
        cur_node = head
        while cur_node:
            new_node = Node(cur_node.val)
            new_node.next = cur_node.next
            cur_node.next = new_node
            cur_node = new_node.next
        
        # 第二步,设置新节点的随机节点
        cur_node = head
        while cur_node:
            if cur_node.random:
                cur_node.next.random = cur_node.random.next
            cur_node = cur_node.next.next
        
        # 第三步,将两个链表分离,设置一个空节点root
        cur_node = head
        root = Node(-1, None, None)
        next_node = root
        while cur_node:
            next_node.next = cur_node.next
            next_node = next_node.next
            cur_node.next = next_node.next
            cur_node = cur_node.next
        return root.next

36. 二叉搜索树与双向链表

 

# Definition for a Node.
class Node(object):
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


class Solution(object):
    def treeToDoublyList(self, root):
        """
        :type root: Node
        :rtype: Node
        """

        def dfs(cur_node):
            if not cur_node:
                return
            dfs(cur_node.left)  # 递归左子树
            if self.pre:  # 修改节点引用
                self.pre.right, cur_node.left = cur_node, self.pre
            else:  # 记录头节点
                self.head = cur_node
            self.pre = cur_node  # 保存 cur
            dfs(cur_node.right)  # 递归右子树

        if not root: return
        self.pre = None
        dfs(root)
        self.head.left, self.pre.right = self.pre, self.head
        return self.head

37. 序列化二叉树

 运用层次遍历的方法思考起来比较简单:

from collections import deque


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


class Codec:

    def serialize(self, root):
        """
        Encodes a tree to a single string.
        :type root: TreeNode
        :rtype: str
        """
        if not root: return []
        ans = []
        queue = deque()
        queue.append(root)
        # 层次遍历
        while queue:
            node = queue.popleft()
            if node:
                ans.append(node.val)
                queue.append(node.left)
                queue.append(node.right)
            else:
                ans.append('null')

        return ans

    def deserialize(self, data):
        """
        Decodes your encoded data to tree.
        :type data: str
        :rtype: TreeNode
        """
        if not data: return
        root = TreeNode(data[0])
        queue = deque()
        queue.append(root)
        i = 1
        while queue:
            node = queue.popleft()
            if data[i] != 'null':
                node.left = TreeNode(data[i])
                queue.append(node.left)
            i += 1
            if data[i] != 'null':
                node.right = TreeNode(data[i])
                queue.append(node.right)
            i += 1
        return root

38. 字符串的排列

class Solution(object):
    def permutation(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        word, res = list(s), []

        # 将固定第x个字符
        def dfs(x):
            if x == len(word) - 1:
                res.append(''.join(word))  # 添加排列方案
                return
            dic = set()
            for i in range(x, len(word)):
                if word[i] in dic: continue  # 重复,因此剪枝
                dic.add(word[i])
                word[i], word[x] = word[x], word[i]  # 交换,将word[i]固定在第x位
                dfs(x + 1)  # 开启固定第x+1位字符
                word[i], word[x] = word[x], word[i]  # 恢复交换

        dfs(0)
        return res

39. 数组中出现次数超过一半的数

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        return nums[int(len(nums)//2)]

摩尔投票法 :

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        votes = 0
        for num in nums:
            if votes == 0: 
                x = num
            if num == x:
                votes += 1
            else:
                votes -= 1
        return x

40. 最小的k个数

 快速排序的进阶版:

class Solution(object):
    def getLeastNumbers(self, arr, k):
        """
        :type arr: List[int]
        :type k: int
        :rtype: List[int]
        """
        if k >= len(arr): return arr

        def quick_sort(left, right):
            i, j = left, right
            while i < j:
                while i < j and arr[j] >= arr[left]: j -= 1
                while i < j and arr[i] <= arr[left]: i += 1
                arr[i], arr[j] = arr[j], arr[i]
            arr[left], arr[i] = arr[i], arr[left]
            if k < i: return quick_sort(left, i - 1)
            if k > i: return quick_sort(i + 1, right)
            return arr[:k]

        return quick_sort(0, len(arr) - 1)

41. 数据流中的中位数

class MedianFinder(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.A = [] # 小顶堆,保存较大的一半
        self.B = [] # 大顶堆,保存较小的一半


    def addNum(self, num):
        """
        :type num: int
        :rtype: None
        """
        if len(self.A) != len(self.B):
            # heappush往堆中添加新值自动建立小根堆
            heappush(self.A, num)
            # 添加新值时取相反数建立大根堆,取出时要再取相反数
            # heappop从堆中弹出返回最小的值
            heappush(self.B, -heappop(self.A))
        else:
            heappush(self.B, -num)
            heappush(self.A, -heappop(self.B))




    def findMedian(self):
        """
        :rtype: float
        """
        if len(self.A) != len(self.B):
            return self.A[0]
        else:
            return (self.A[0] - self.B[0]) / 2.0

# Your MedianFinder object will be instantiated and called as such:
# obj = MedianFinder()
# obj.addNum(num)
# param_2 = obj.findMedian()

42. 连续子数组的最大和

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        ans = float('-inf')
        pre = ans
        for num in nums:
            pre = max(pre + num, num)
            ans = max(pre, ans)
        return ans

43. 1~n整数中1出现的次数

统计每一位上出现1的次数:

class Solution(object):
    def countDigitOne(self, n):
        """
        :type n: int
        :rtype: int
        """
        li = list(str(n))
        count = len(li)
        ans = 0
        for i in range(count):
            digit = 10 ** (count-i-1)
            high = 0
            for j in range(i):
                high += int(li[j]) * 10 ** (i-j-1)
            ans += (high + 1) * digit
            low = 0
            for k in range(i+1, count):
                low += int(li[k]) * 10 ** (count - k - 1)
            if li[i] == '0':
                ans -= digit
            if li[i] == '1':
                ans -= digit - low - 1
        return ans

44. 数字序列中某一位的数字

class Solution(object):
    def findNthDigit(self, n):
        """
        :type n: int
        :rtype: int
        """
        # digit:数字位数(0,1,2...)
        # start:每位数起始数字(1,10,100...)
        # count:每位数数位个数(9,180,2700...)
        digit, start, count = 1, 1, 9
        # n:数位
        # num:数字
        # 1:确定n所在数字的位数记为digit
        while n > count:
            n -= count
            start *= 10
            digit += 1
            count = 9 * start * digit
        # 2:确定n所在的数字记为num
        num = start + (n - 1) // digit
        # 3:确定n在num中的哪一位并返回
        return int(str(num)[(n - 1) % digit])

45. 把数组排成最小的数 

class Solution(object):
    def minNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        def quick_sort(l, r):
            if l >= r: return
            i, j = l, r
            while i < j:
                while strs[j] + strs[l] >= strs[l] + strs[j] and i < j: j -= 1
                while strs[i] + strs[l] <= strs[l] + strs[i] and i < j: i += 1
                strs[i], strs[j] = strs[j], strs[i]
            strs[i], strs[l] = strs[l], strs[i]
            quick_sort(l, i - 1)
            quick_sort(i + 1, r)

        strs = [str(num) for num in nums]
        quick_sort(0, len(strs) - 1)
        return ''.join(strs)

46. 把数字翻译成字符串 

class Solution(object):
    def translateNum(self, num):
        """
        :type num: int
        :rtype: int
        """
        str_num = str(num)
        n = len(str_num)
        p, q = 1, 1
        for i in range(2, n + 1):
            if str_num[i - 2] == '1' or \
            (str_num[i - 2] == '2' and str_num[i - 1] < '6'):
                p, q = q, p+q
            else:
                p, q = q, q
        return q

47. 礼物的最大价值 

class Solution(object):
    def maxValue(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        m = len(grid)
        n = len(grid[0])
        dp = [[0 for _ in range(n)] for _ in range(m)]
        dp[m-1][n-1] = grid[m-1][n-1]
        for i in range(m-2, -1, -1):
            dp[i][n-1] = dp[i+1][n-1] + grid[i][n-1]
        for j in range(n-2, -1, -1):
            dp[m-1][j] = dp[m-1][j+1] + grid[m-1][j]
        for i in range(m-2, -1, -1):
            for j in range(n-2, -1, -1):
                dp[i][j] = max(dp[i+1][j], dp[i][j+1]) + grid[i][j]
        return dp[0][0]

或者直接在grid上修改

class Solution(object):
    def maxValue(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        m = len(grid)
        n = len(grid[0])
        for i in range(m):
            for j in range(n):
                if i == 0 and j == 0:
                    continue
                elif i == 0:
                    grid[i][j] += grid[i][j-1]
                elif j == 0:
                    grid[i][j] += grid[i-1][j]
                else:
                    grid[i][j] += max(grid[i-1][j], grid[i][j-1])
        return grid[m-1][n-1]

48. 最长不含重复字符的子字符串

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        dic, ans, left = {}, 0, -1
        for right in range(len(s)):
            if s[right] in dic:
                left = max(dic[s[right]], left)  # 更新左指针 left
            dic[s[right]] = right  # 哈希表记录
            ans = max(ans, right - left)  # 更新结果
        return ans

49. 丑数

class Solution(object):
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        res = [1]
        v2, v3, v5 = 0, 0, 0
        while len(res) < n:
            a2, a3, a5 = res[v2]*2, res[v3]*3, res[v5]*5
            tmp = min(a2, a3, a5)
            if tmp == a2:
                v2 += 1
            if tmp == a3:
                v3 += 1
            if tmp == a5:
                v5 += 1
            res.append(tmp)
        return res[-1]

50. 第一个只出现一次的字符

import collections
class Solution(object):
    def firstUniqChar(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s:
            return " "
        hashtable = collections.defaultdict(int)
        ans = []
        for val in s:
            if val not in hashtable:
                ans.append(val)
                hashtable[val] = 1
            else:
                hashtable[val] += 1
                if hashtable[val] == 2:
                    ans.remove(val)
        if not ans:
            return " "
        else:
            return ans[0]

更优美的写法:

class Solution(object):
    def firstUniqChar(self, s):
        """
        :type s: str
        :rtype: str
        """
        dic = {}
        for c in s:
            dic[c] = not c in dic
        for c in s:
            if dic[c]: return c
        return ' '

51. 数组中的逆序对

 归并排序的合并环节中统计逆序对的个数(每插入一个后序节点到前面统计一次),完成归并排序时也随之完成所有逆序对的统计。

class Solution(object):
    def reversePairs(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        def merge_sort(left, right):
            if left < right:
                mid = (left + right) // 2
                count = merge_sort(left, mid) + merge_sort(mid + 1, right)
                i, j = left, mid + 1
                tmp = []
                while i <= mid and j <= right:
                    if nums[i] <= nums[j]:
                        tmp.append(nums[i])
                        i += 1
                    else:
                        tmp.append(nums[j])
                        count += mid - i + 1
                        j += 1
                while i <= mid:
                    tmp.append(nums[i])
                    i += 1
                while j <= right:
                    tmp.append(nums[j])
                    j += 1
                nums[left:right + 1] = tmp
            else:
                return 0
            return count

        return merge_sort(0, len(nums) - 1)

52. 两个链表的第一个公共节点

输入两个链表,找出它们的第一个公共节点。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        A, B = headA, headB
        while A != B:
            A = A.next if A else headB
            B = B.next if B else headA
        return A

如果没有公共节点,最后A和B会一起指向None

53-I. 在排序数组中查找数字

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        return nums.count(target)

或者使用二分法(一旦遇到查找问题首先想到二分法

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        def helper(tar):
            left, right = 0, len(nums) - 1
            while left <= right:
                mid = (left + right) // 2
                if nums[mid] <= tar: left = mid + 1
                else: right = mid - 1
            return left
        return helper(target) - helper(target - 1)

helper函数:找到大于tar的第一个位置

53-II. 0~n-1中缺失的数字

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] == mid:
                left = mid + 1
            else:
                right = mid - 1
        return left

54. 二叉搜索树第K大节点 

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

class Solution(object):
    def kthLargest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        if not root:
            return

        def dfs(curnode):
            res.append(curnode.val)
            if curnode.left:
                dfs(curnode.left)
            if curnode.right:
                dfs(curnode.right)
            return res

        res = []
        dfs(root)
        res.sort()
        return res[-k]

另一种方法:中序遍历后提前返回节点

class Solution(object):
    def kthLargest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        def dfs(root):
            if not root: return
            dfs(root.right)
            if self.k == 0: return
            self.k -= 1
            if self.k == 0: self.res = root.val
            dfs(root.left)

        self.k = k
        dfs(root)
        return self.res

55-I. 二叉树的深度

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

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        li = []
        def dfs(curnode, curdepth):
            if not curnode:
                li.append(curdepth)
                return
            curdepth += 1
            dfs(curnode.left, curdepth)
            dfs(curnode.right, curdepth)
            return
        dfs(root, 0)
        return max(li)

55-II. 平衡二叉树

1. 自顶向下

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

class Solution(object):
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        def height(curnode):
            if not curnode:
                return 0
            return max(height(curnode.left), height(curnode.right)) + 1

        if not root:
            return True
        return abs(height(root.left) - height(root.right)) <= 1 \
               and self.isBalanced(root.left) \
               and self.isBalanced(root.right)

2. 自底向上

class Solution(object):
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        def height(curnode):
            if not curnode:
                return 0
            leftHeight = height(curnode.left)
            rightHeight = height(curnode.right)
            if leftHeight == -1 or rightHeight == -1 or abs(leftHeight - rightHeight) > 1:
                return -1
            else:
                return max(leftHeight, rightHeight) + 1

        return height(root) >= 0

56-I. 数组中数字出现的次数

相同数字异或为0

class Solution(object):
    def singleNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        # n = a ^ b
        # 因为存在两个不同的数a,b都只出现了一次
        # 因此a,b的二进制位必然不完全相同
        # 找到n第一个为1的位(a,b首个不同的二进制位)
        # 以此为依据将nums分成两个数组x,y
        # 此时a,b被分开放到x,y中
        x, y, n, m = 0, 0, 0, 1
        for num in nums:         # 1. 遍历异或
            n ^= num
        while n & m == 0:        # 2. 循环左移,计算 m
            m <<= 1       
        for num in nums:         # 3. 遍历 nums 分组
            if num & m: x ^= num # 4. 当 num & m != 0
            else: y ^= num       # 4. 当 num & m == 0
        return x, y              # 5. 返回出现一次的数字

56-II. 数组中数字出现的次数

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        counts = [0] * 32
        for num in nums:
            for j in range(32):
                counts[j] += num & 1
                num >>= 1
        res, m = 0, 3
        for i in range(32):
            res <<= 1
            res |= counts[31 - i] % m
        return res if counts[31] % m == 0 else ~(res ^ 0xffffffff)

57-I. 和为s的两个数字

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        left, right = 0, len(nums) - 1
        while left < right:
            if nums[left] + nums[right] > target:
                right -= 1
            elif nums[left] + nums[right] < target:
                left += 1
            else:
                return [nums[left], nums[right]]

57-II. 和为s的连续正数序列

class Solution(object):
    def findContinuousSequence(self, target):
        """
        :type target: int
        :rtype: List[List[int]]
        """
        i, j = 1, 2
        res = []
        while i < j:
            tmp = (i+j)*(j-i+1)/2
            if tmp < target:
                j += 1
            elif tmp > target:
                i += 1
            else:
                res.append(list(range(i, j+1)))
                i += 1
        return res

58-I. 反转单词顺序

class Solution(object):
    def reverseWords(self, s):
        """
        :type s: str
        :rtype: str
        """
        s = s.strip()  # 删除首尾空格
        i = j = len(s) - 1
        res = []
        while i >= 0:
            while i >= 0 and s[i] != ' ': 
                i -= 1  # 搜索首个空格
            res.append(s[i + 1: j + 1])  # 添加单词
            while s[i] == ' ': 
                i -= 1  # 跳过单词间空格
            j = i  # j 指向下个单词的尾字符
        return ' '.join(res)

58-II. 左旋转字符串

class Solution:
    def reverseLeftWords(self, s: str, n: int):
        return s[n:] + s[:n]

class Solution:
    def reverseLeftWords(self, s: str, n: int):
        res = []
        for i in range(n, len(s)):
            res.append(s[i])
        for i in range(n):
            res.append(s[i])
        return ''.join(res)

class Solution:
    def reverseLeftWords(self, s: str, n: int):
        res = ""
        for i in range(n, len(s)):
            res += s[i]
        for i in range(n):
            res += s[i]
        return res

由于字符串为不可变对象,因此每轮都要新建字符串,效率低下。

59-I. 滑动窗口的最大值

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        ans = []
        if not nums: return ans
        for i in range(len(nums)-k+1):
            tmp = nums[i:i+k]
            ans.append(max(tmp))
        return ans

59-II. 队列的最大值

 

class MaxQueue(object):

    def __init__(self):
        self.queue = deque()
        self.maxvalue = deque()


    def max_value(self):
        """
        :rtype: int
        """
        if not self.maxvalue:
            return -1
        else:
            return self.maxvalue[0]


    def push_back(self, value):
        """
        :type value: int
        :rtype: None
        """
        self.queue.append(value)
        while self.maxvalue and self.maxvalue[-1] < value:
            self.maxvalue.pop()
        self.maxvalue.append(value)



    def pop_front(self):
        """
        :rtype: int
        """
        if not self.queue:
            return -1
        else:
            tmp = self.queue.popleft()
            if self.maxvalue and tmp == self.maxvalue[0]:
                self.maxvalue.popleft()
            return tmp

60. n个骰子的点数

class Solution:
    def dicesProbability(self, n: int):
        # i为有i个骰子的情况
        for i in range(1,n+1):
            if i == 1:
                dp = [1/6] * 6
            else:
                dp = [0] * (5 * i + 1)
                for j in range(5*(i-1)+1):
                    for k in range(j, j+6):
                        dp[k] += pre[j] / 6
            pre = dp
        return dp

61. 扑克牌中的顺子

class Solution(object):
    def isStraight(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        nums.sort()
        k = nums.count(0)
        right = k + 1
        while right < 5:
            if nums[right] == nums[right-1]:
                return False
            if nums[right] != nums[right - 1] + 1:
                if k < nums[right] - nums[right-1] - 1:
                    return False
                else:
                    k -= nums[right] - nums[right-1] - 1
            right += 1
        return True

62. 圆圈中最后剩下的数字(约瑟夫环)

class Solution(object):
    def lastRemaining(self, n, m):
        """
        :type n: int
        :type m: int
        :rtype: int
        """
        x = 0
        for i in range(2, n + 1):
            x = (x + m) % i
        return x

63. 股票的最大利润

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        ans = 0
        low = float('inf')  # 标记最低买入价格
        for price in prices:
            ans = max(ans, price - low)
            low = min(low, price)
        return ans

不需要下标信息的时候直接for val in prices节省时间

64. 求1+2+...+n

class Solution(object):
    def sumNums(self, n):
        """
        :type n: int
        :rtype: int
        """
        self.res = 0
        n > 1 and self.sumNums(n - 1)
        self.res += n
        return self.res

65. 不用加减乘除做加法

class Solution(object):
    def add(self, a, b):
        """
        :type a: int
        :type b: int
        :rtype: int
        """
        x = 0xffffffff
        a, b = a & x, b & x
        # a为无进位和,b为进位
        while b != 0:
            a, b = (a ^ b), (a & b) << 1 & x
        return a if a <= 0x7fffffff else ~(a ^ x)

66. 构建乘积数组

class Solution(object):
    def constructArr(self, a):
        """
        :type a: List[int]
        :rtype: List[int]
        """
        ans, tmp = [1] * len(a), 1
        # 下三角
        for i in range(1, len(a)):
            ans[i] = ans[i - 1] * a[i - 1]
        # 上三角
        for i in range(len(a) - 2, -1, -1):
            tmp *= a[i + 1]
            ans[i] *= tmp
        return ans

67. 把字符串转换成整数

class Solution(object):
    def strToInt(self, str):
        """
        :type str: str
        :rtype: int
        """
        ans = ''
        nums = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}
        start = -1
        for i in range(len(str)):
            if str[i] == '-' or str[i] == '+' or str[i] in nums:
                start = i
                ans += str[i]
                break
            elif str[i] == ' ':
                continue
            else:
                return 0
        if start == -1:
            return 0
        else:
            for j in range(start+1, len(str)):
                if str[j] in nums:
                    ans += str[j]
                else:
                    break
        if len(ans) == 1 and (ans[0] == '-' or ans [0] == '+'):
            return 0
        if int(ans) > 2 ** 31 - 1:
            return 2 ** 31 - 1
        if int(ans) < - 2 ** 31:
            return - 2 ** 31
        return int(ans)

class Solution(object):
    def strToInt(self, str):
        """
        :type str: str
        :rtype: int
        """
        str = str.strip()                      # 删除首尾空格
        if not str: return 0                   # 字符串为空则直接返回
        res, i, sign = 0, 1, 1                 # i标记数字开始位置,有符号i=1无符号i=0
        int_max, int_min, bndry = 2 ** 31 - 1, -2 ** 31, 2 ** 31 // 10
        if str[0] == '-': sign = -1            # 保存负号
        elif str[0] != '+': i = 0              # 若无符号位,则需从 i = 0 开始数字拼接
        for c in str[i:]:
            if not '0' <= c <= '9' : break     # 遇到非数字的字符则跳出
            # 数字越界处理
            if res > bndry or res == bndry and c > '7': 
                if sign == 1:
                    return int_max
                else:
                    return int_min
            # 数字拼接
            res = 10 * res + ord(c) - ord('0')
        return sign * res

68-I. 二叉搜索树最近的公共祖先

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        cur = root
        while cur.right or cur.left:
            if cur.val > p.val and cur.val > q.val:
                cur = cur.left
            elif cur.val < p.val and cur.val < q.val:
                cur = cur.right
            else:
                return cur

68-II. 二叉树最近的公共祖先

1. 先建立哈希表存储每个节点的父节点,找到p的所有祖先节点,再寻找q的祖先节点,一旦找到共同的祖先节点即返回

import collections


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


class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        # {key:value} key为子节点,value为父节点
        parent = collections.defaultdict(int)

        def dfs(curNode, preNode):
            if not curNode:
                return
            if curNode != root:
                parent[curNode] = preNode
            dfs(curNode.right, curNode)
            dfs(curNode.left, curNode)

        dfs(root, root)

        pathp = []

        def findpath(childNode, path):
            path.append(childNode)
            if childNode not in parent:
                return
            findpath(parent[childNode], path)

        findpath(p, pathp)

        def findnode(childnode):
            if childnode not in pathp:
                return findnode(parent[childnode])
            return childnode

        return findnode(q)

2. 分情况讨论,当p/q分别在某节点的左右子树时,该节点为最近祖先节点

class Solution:
    def lowestCommonAncestor(self, root, p, q):
        if not root or root == p or root == q: return root
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        # 1.left和right都为空:root的左右子树都不包含p/q
        if not left and not right: return # 1.
        # 3.4.left和right不同时为空:
        # 3.left为空right不为空,p/q都不在root的左子树中
        if not left: return right
        # 4.right为空left不为空,p/q都不在root的右子树中
        if not right: return left
        # 2.left和right都不为空,则root为最近公共祖先
        return root
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值