Python版剑指Offer题解

本题解配合leetcode中剑指Offer刷题使用
参考链接:图解算法数据结构

文章目录

  • 剑指 Offer 03. 数组中重复的数字
  • 剑指 Offer 04. 二维数组中的查找
  • 剑指 Offer 05. 替换空格
  • 剑指 Offer 06. 从尾到头打印链表
  • 剑指 Offer 07. 重建二叉树
  • 剑指 Offer 09. 用两个栈实现队列
  • 剑指 Offer 10- I. 斐波那契数列
  • 剑指 Offer 10- II. 青蛙跳台阶问题
  • 剑指 Offer 11. 旋转数组的最小数字
  • 剑指 Offer 12. 矩阵中的路径
  • 剑指 Offer 13. 机器人的运动范围
  • 剑指 Offer 14- I. 剪绳子
  • 剑指 Offer 14- II. 剪绳子 II
  • 剑指 Offer 15. 二进制中1的个数
  • 剑指 Offer 16. 数值的整数次方
  • 剑指 Offer 17. 打印从1到最大的n位数
  • 剑指 Offer 18. 删除链表的节点
  • 剑指 Offer 19. 正则表达式匹配
  • 剑指 Offer 20. 表示数值的字符串
  • 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
  • 剑指 Offer 22. 链表中倒数第k个节点
  • 剑指 Offer 24. 反转链表
  • 剑指 Offer 25. 合并两个排序的链表
  • 剑指 Offer 26. 树的子结构
  • 剑指 Offer 27. 二叉树的镜像
  • 剑指 Offer 28. 对称的二叉树
  • 剑指 Offer 29. 顺时针打印矩阵
  • 剑指 Offer 30. 包含min函数的栈
  • 剑指 Offer 31. 栈的压入、弹出序列
  • 剑指 Offer 32 - I. 从上到下打印二叉树
  • 剑指 Offer 32 - II. 从上到下打印二叉树 II
  • 剑指 Offer 32 - III. 从上到下打印二叉树 III
  • 剑指 Offer 33. 二叉搜索树的后序遍历序列
  • 剑指 Offer 34. 二叉树中和为某一值的路径
  • 剑指 Offer 35. 复杂链表的复制
  • 剑指 Offer 36. 二叉搜索树与双向链表
  • 剑指 Offer 37. 序列化二叉树
  • 剑指 Offer 38. 字符串的排列
  • 剑指 Offer 39. 数组中出现次数超过一半的数字
  • 剑指 Offer 40. 最小的k个数
  • 剑指 Offer 41. 数据流中的中位数
  • 剑指 Offer 42. 连续子数组的最大和
  • 剑指 Offer 43. 1~n 整数中 1 出现的次数
  • 剑指 Offer 44. 数字序列中某一位的数字
  • 剑指 Offer 45. 把数组排成最小的数
  • 剑指 Offer 46. 把数字翻译成字符串
  • 剑指 Offer 47. 礼物的最大价值
  • 剑指 Offer 48. 最长不含重复字符的子字符串
  • 剑指 Offer 49. 丑数
  • 剑指 Offer 50. 第一个只出现一次的字符
  • 剑指 Offer 51. 数组中的逆序对
  • 剑指 Offer 52. 两个链表的第一个公共节点
  • 剑指 Offer 53 - I. 在排序数组中查找数字 I
  • 剑指 Offer 53 - II. 0~n-1中缺失的数字
  • 剑指 Offer 54. 二叉搜索树的第k大节点
  • 剑指 Offer 55 - I. 二叉树的深度
  • 剑指 Offer 55 - II. 平衡二叉树
  • 剑指 Offer 56 - I. 数组中数字出现的次数
  • 剑指 Offer 56 - II. 数组中数字出现的次数 II
  • 剑指 Offer 57. 和为s的两个数字
  • 剑指 Offer 57 - II. 和为s的连续正数序列
  • 剑指 Offer 58 - I. 翻转单词顺序
  • 剑指 Offer 58 - II. 左旋转字符串
  • 剑指 Offer 59 - I. 滑动窗口的最大值
  • 剑指 Offer 59 - II. 队列的最大值
  • 剑指 Offer 60. n个骰子的点数
  • 剑指 Offer 61. 扑克牌中的顺子
  • 剑指 Offer 62. 圆圈中最后剩下的数字
  • 剑指 Offer 63. 股票的最大利润
  • 剑指 Offer 64. 求1+2+…+n
  • 剑指 Offer 65. 不用加减乘除做加法
  • 剑指 Offer 66. 构建乘积数组
  • 剑指 Offer 67. 把字符串转换成整数
  • 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
  • 剑指 Offer 68 - II. 二叉树的最近公共祖先

剑指 Offer 03. 数组中重复的数字

class Solution:def findRepeatNumber(self, nums: [int]) -> int:dic = set()for num in nums:if num in dic: return numdic.add(num)return -1

剑指 Offer 04. 二维数组中的查找

### 暴力解法
class Solution:def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:if not matrix:return Falsen=len(matrix)m=len(matrix[0])for i in range(n):for j in range(m):if matrix[i][j] == target:return Truereturn False
###  线性查找
class Solution:def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:if not matrix:return Falsem, n = len(matrix), len(matrix[0])row, col = 0, n - 1while row < m and col >= 0:if matrix[row][col] == target:return Trueif matrix[row][col] < target:row += 1else:col -= 1return False

剑指 Offer 05. 替换空格

# 解法1
class Solution:def replaceSpace(self, s: str) -> str:return s.replace(" ","%20")
# 解法2
class Solution:def replaceSpace(self, s: str) -> str:res = []for c in s:if c == ' ': res.append("%20")else: res.append(c)return "".join(res)

剑指 Offer 06. 从尾到头打印链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def reversePrint(self, head: ListNode) -> List[int]:stack = []while head:stack.append(head.val)head = head.nextreturn stack[::-1]

剑指 Offer 07. 重建二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:def myBuildTree(preorder_left: int, preorder_right: int, inorder_left: int, inorder_right: int):if preorder_left > preorder_right:return None# 前序遍历中的第一个节点就是根节点preorder_root = preorder_left# 在中序遍历中定位根节点inorder_root = index[preorder[preorder_root]]# 先把根节点建立出来root = TreeNode(preorder[preorder_root])# 得到左子树中的节点数目size_left_subtree = inorder_root - inorder_left# 递归地构造左子树,并连接到根节点# 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素root.left = myBuildTree(preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1)# 递归地构造右子树,并连接到根节点# 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素root.right = myBuildTree(preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right)return rootn = len(preorder)# 构造哈希映射,帮助我们快速定位根节点index = {element: i for i, element in enumerate(inorder)}return myBuildTree(0, n - 1, 0, n - 1)

剑指 Offer 09. 用两个栈实现队列

class CQueue:def __init__(self):self.A, self.B = [], []def appendTail(self, value: int) -> None:self.A.append(value)def deleteHead(self) -> int:if self.B: return self.B.pop()if not self.A: return -1while self.A:self.B.append(self.A.pop())return self.B.pop()# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()

剑指 Offer 10- I. 斐波那契数列

class Solution:def fib(self, n: int) -> int:a, b = 0, 1for _ in range(n):a, b = b, a + breturn a % 1000000007
class Solution:def fib(self, n: int) -> int:if n<2:return ndp=[0,1]for i in range(2, n + 1):dp.append(dp[i - 1] + dp[i - 2])return dp[n] % 1000000007

剑指 Offer 10- II. 青蛙跳台阶问题

class Solution:def numWays(self, n: int) -> int:if n==0 or n==1:return 1if n==2:return 2a,b=1,1for i in range(n):a,b=b,a+breturn a%1000000007

剑指 Offer 11. 旋转数组的最小数字

class Solution:def minArray(self, numbers: List[int]) -> int:numbers.sort()return numbers[0]
class Solution:def minArray(self, numbers: List[int]) -> int:low, high = 0, len(numbers) - 1while low < high:pivot = low + (high - low) // 2if numbers[pivot] < numbers[high]:high = pivot elif numbers[pivot] > numbers[high]:low = pivot + 1else:high -= 1return numbers[low]

剑指 Offer 12. 矩阵中的路径

class Solution:def exist(self, board: List[List[str]], word: str) -> bool:def dfs(i, j, k):if not 0 <= i < len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]: return Falseif k == len(word) - 1: return Trueboard[i][j] = ''res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)board[i][j] = word[k]return resfor i in range(len(board)):for j in range(len(board[0])):if dfs(i, j, 0): return Truereturn False

剑指 Offer 13. 机器人的运动范围

class Solution:def movingCount(self, m: int, n: int, k: int) -> int:def dfs(i, j, si, sj):if i >= m or j >= n or k < si + sj or (i, j) in visited: return 0visited.add((i,j))return 1 + dfs(i + 1, j, si + 1 if (i + 1) % 10 else si - 8, sj) + dfs(i, j + 1, si, sj + 1 if (j + 1) % 10 else sj - 8)visited = set()return dfs(0, 0, 0, 0)
def digitsum(n):ans = 0while n:ans += n % 10n //= 10return ansclass Solution:def movingCount(self, m: int, n: int, k: int) -> int:vis = set([(0, 0)])for i in range(m):for j in range(n):if ((i - 1, j) in vis or (i, j - 1) in vis) and digitsum(i) + digitsum(j) <= k:vis.add((i, j))return len(vis)

剑指 Offer 14- I. 剪绳子

class Solution:def cuttingRope(self, n: int) -> int:dp = [0] * (n + 1)dp[2] = 1for i in range(3, n + 1):for j in range(2, i):dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))return dp[n]
class Solution:def cuttingRope(self, n: int) -> int:if n < 4:return n - 1res = 1while n > 4:res *=3n -= 3return res * n

剑指 Offer 14- II. 剪绳子 II

class Solution:def cuttingRope(self, n: int) -> int:if n < 4:return n - 1res = 1while n > 4:res = res * 3 % 1000000007n -= 3return res * n % 1000000007

剑指 Offer 15. 二进制中1的个数

class Solution:def hammingWeight(self, n: int) -> int:ret = 0while n:n &= n - 1ret += 1return ret

剑指 Offer 16. 数值的整数次方

class Solution:def myPow(self, x: float, n: int) -> float:if x == 0: return 0res = 1if n < 0: x, n = 1 / x, -nwhile n:if n & 1: res *= xx *= xn >>= 1return res

剑指 Offer 17. 打印从1到最大的n位数

class Solution:def printNumbers(self, n: int) -> List[int]:return list(range(1, 10 ** n))

剑指 Offer 18. 删除链表的节点

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:def deleteNode(self, head: ListNode, val: int) -> ListNode:if head.val == val: return head.nextpre, cur = head, head.nextwhile cur and cur.val != val:pre, cur = cur, cur.nextif cur: pre.next = cur.nextreturn head

剑指 Offer 19. 正则表达式匹配

class Solution:def isMatch(self, s: str, p: str) -> bool:m, n = len(s) + 1, len(p) + 1dp = [[False] * n for _ in range(m)]dp[0][0] = True# 初始化首行for j in range(2, n, 2):dp[0][j] = dp[0][j - 2] and p[j - 1] == '*'# 状态转移for i in range(1, m):for j in range(1, n):if p[j - 1] == '*':if dp[i][j - 2]: dp[i][j] = True                              # 1.elif dp[i - 1][j] and s[i - 1] == p[j - 2]: dp[i][j] = True   # 2.elif dp[i - 1][j] and p[j - 2] == '.': dp[i][j] = True        # 3.else:if dp[i - 1][j - 1] and s[i - 1] == p[j - 1]: dp[i][j] = True # 1.elif dp[i - 1][j - 1] and p[j - 1] == '.': dp[i][j] = True    # 2.return dp[-1][-1]

剑指 Offer 20. 表示数值的字符串

class Solution:def isNumber(self, s: str) -> bool:states = [{ ' ': 0, 's': 1, 'd': 2, '.': 4 }, # 0. start with 'blank'{ 'd': 2, '.': 4 } ,                # 1. 'sign' before 'e'{ 'd': 2, '.': 3, 'e': 5, ' ': 8 }, # 2. 'digit' before 'dot'{ 'd': 3, 'e': 5, ' ': 8 },         # 3. 'digit' after 'dot'{ 'd': 3 },                         # 4. 'digit' after 'dot' (‘blank’ before 'dot'){ 's': 6, 'd': 7 },                 # 5. 'e'{ 'd': 7 },                         # 6. 'sign' after 'e'{ 'd': 7, ' ': 8 },                 # 7. 'digit' after 'e'{ ' ': 8 }                          # 8. end with 'blank']p = 0                           # start with state 0for c in s:if '0' <= c <= '9': t = 'd' # digitelif c in "+-": t = 's'     # signelif c in "eE": t = 'e'     # e or Eelif c in ". ": t = c       # dot, blankelse: t = '?'               # unknownif t not in states[p]: return Falsep = states[p][t]return p in (2, 3, 7, 8)

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

class Solution:def exchange(self, nums: List[int]) -> List[int]:i, j = 0, len(nums) - 1while i < j:while i < j and nums[i] & 1 == 1: i += 1while i < j and nums[j] & 1 == 0: j -= 1nums[i], nums[j] = nums[j], nums[i]return nums
class Solution:def exchange(self, nums: List[int]) -> List[int]:odd = []even = []for num in nums:if num % 2 == 1:odd.append(num)else:even.append(num)return odd + even

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

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:former, latter = head, headfor _ in range(k):if not former: returnformer = former.nextwhile former:former, latter = former.next, latter.nextreturn latter

剑指 Offer 24. 反转链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def reverseList(self, head: ListNode) -> ListNode:cur, pre = head, Nonewhile cur:tmp = cur.next # 暂存后继节点 cur.nextcur.next = pre # 修改 next 引用指向pre = cur      # pre 暂存 curcur = tmp      # cur 访问下一节点return pre

剑指 Offer 25. 合并两个排序的链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:cur = dum = ListNode(0)while l1 and l2:if l1.val < l2.val:cur.next, l1 = l1, l1.nextelse:cur.next, l2 = l2, l2.nextcur = cur.nextcur.next = l1 if l1 else l2return dum.next

剑指 Offer 26. 树的子结构

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:def recur(A, B):if not B: return Trueif not A or A.val != B.val: return Falsereturn recur(A.left, B.left) and recur(A.right, B.right)return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))

剑指 Offer 27. 二叉树的镜像

class Solution:def mirrorTree(self, root: TreeNode) -> TreeNode:if not root: returnroot.left, root.right = self.mirrorTree(root.right), self.mirrorTree(root.left)return root

剑指 Offer 28. 对称的二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isSymmetric(self, root: TreeNode) -> bool:def recur(L, R):if not L and not R: return Trueif not L or not R or L.val != R.val: return Falsereturn recur(L.left, R.right) and recur(L.right, R.left)return recur(root.left, root.right) if root else True

剑指 Offer 29. 顺时针打印矩阵

class Solution:def spiralOrder(self, matrix:[[int]]) -> [int]:if not matrix: return []l, r, t, b, res = 0, len(matrix[0]) - 1, 0, len(matrix) - 1, []while True:for i in range(l, r + 1): res.append(matrix[t][i]) # left to rightt += 1if t > b: breakfor i in range(t, b + 1): res.append(matrix[i][r]) # top to bottomr -= 1if l > r: breakfor i in range(r, l - 1, -1): res.append(matrix[b][i]) # right to leftb -= 1if t > b: breakfor i in range(b, t - 1, -1): res.append(matrix[i][l]) # bottom to topl += 1if l > r: breakreturn res

剑指 Offer 30. 包含min函数的栈

class MinStack:def __init__(self):"""initialize your data structure here."""self.A, self.B = [], []def push(self, x: int) -> None:self.A.append(x)if not self.B or self.B[-1] >= x:self.B.append(x)def pop(self) -> None:if self.A.pop() == self.B[-1]:self.B.pop()def top(self) -> int:return self.A[-1]def min(self) -> int: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()

剑指 Offer 31. 栈的压入、弹出序列

class Solution:def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:stack, i = [], 0for num in pushed:stack.append(num) # num 入栈while stack and stack[-1] == popped[i]: # 循环判断与出栈stack.pop()i += 1return not stack

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

class Solution:def levelOrder(self, root: TreeNode) -> 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

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

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def levelOrder(self, root: TreeNode) -> 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

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

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def levelOrder(self, root: TreeNode) -> 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

剑指 Offer 33. 二叉搜索树的后序遍历序列

class Solution:def verifyPostorder(self, postorder: [int]) -> bool:def recur(i, j):if i >= j: return Truep = iwhile postorder[p] < postorder[j]: p += 1m = pwhile postorder[p] > postorder[j]: p += 1return p == j and recur(i, m - 1) and recur(m, j - 1)return recur(0, len(postorder) - 1)

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

# 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 pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:res, path = [], []def recur(root, tar):if not root: returnpath.append(root.val)tar -= root.valif tar == 0 and not root.left and not root.right:res.append(list(path))recur(root.left, tar)recur(root.right, tar)path.pop()recur(root, sum)return res

剑指 Offer 35. 复杂链表的复制

"""
# Definition for a Node.
class Node:def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):self.val = int(x)self.next = nextself.random = random
"""
class Solution:def copyRandomList(self, head: 'Node') -> 'Node':if not head: returndic = {}# 1. 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射cur = headwhile cur:dic[cur] = Node(cur.val)cur = cur.nextcur = head# 2. 构建新节点的 next 和 random 指向while cur:dic[cur].next = dic.get(cur.next)dic[cur].random = dic.get(cur.random)cur = cur.next# 3. 返回新链表的头节点return dic[head]

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

"""
# Definition for a Node.
class Node:def __init__(self, val, left=None, right=None):self.val = valself.left = leftself.right = right
"""
class Solution:def treeToDoublyList(self, root: 'Node') -> 'Node':def dfs(cur):if not cur: returndfs(cur.left) # 递归左子树if self.pre: # 修改节点引用self.pre.right, cur.left = cur, self.preelse: # 记录头节点self.head = curself.pre = cur # 保存 curdfs(cur.right) # 递归右子树if not root: returnself.pre = Nonedfs(root)self.head.left, self.pre.right = self.pre, self.headreturn self.head

剑指 Offer 37. 序列化二叉树

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Codec:def serialize(self, root):if not root: return "[]"queue = collections.deque()queue.append(root)res = []while queue:node = queue.popleft()if node:res.append(str(node.val))queue.append(node.left)queue.append(node.right)else: res.append("null")return '[' + ','.join(res) + ']'def deserialize(self, data):if data == "[]": returnvals, i = data[1:-1].split(','), 1root = TreeNode(int(vals[0]))queue = collections.deque()queue.append(root)while queue:node = queue.popleft()if vals[i] != "null":node.left = TreeNode(int(vals[i]))queue.append(node.left)i += 1if vals[i] != "null":node.right = TreeNode(int(vals[i]))queue.append(node.right)i += 1return root# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))

剑指 Offer 38. 字符串的排列

class Solution:def permutation(self, s: str) -> List[str]:c, res = list(s), []def dfs(x):if x == len(c) - 1:res.append(''.join(c))   # 添加排列方案returndic = set()for i in range(x, len(c)):if c[i] in dic: continue # 重复,因此剪枝dic.add(c[i])c[i], c[x] = c[x], c[i]  # 交换,将 c[i] 固定在第 x 位dfs(x + 1)               # 开启固定第 x + 1 位字符c[i], c[x] = c[x], c[i]  # 恢复交换dfs(0)return res

剑指 Offer 39. 数组中出现次数超过一半的数字

class Solution:def majorityElement(self, nums: List[int]) -> int:counts = collections.Counter(nums)return max(counts.keys(), key=counts.get)
class Solution:def majorityElement(self, nums: List[int]) -> int:nums.sort()return nums[len(nums) // 2]

剑指 Offer 40. 最小的k个数

class Solution:def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:arr.sort()return arr[:k]

剑指 Offer 41. 数据流中的中位数

from heapq import *class MedianFinder:def __init__(self):self.A = [] # 小顶堆,保存较大的一半self.B = [] # 大顶堆,保存较小的一半def addNum(self, num: int) -> None:if len(self.A) != len(self.B):heappush(self.A, num)heappush(self.B, -heappop(self.A))else:heappush(self.B, -num)heappush(self.A, -heappop(self.B))def findMedian(self) -> float:return self.A[0] if len(self.A) != len(self.B) else (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()

剑指 Offer 42. 连续子数组的最大和

class Solution:def maxSubArray(self, nums: List[int]) -> int:for i in range(1, len(nums)):nums[i] += max(nums[i - 1], 0)return max(nums)

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

class Solution:def countDigitOne(self, n: int) -> int:digit, res = 1, 0high, cur, low = n // 10, n % 10, 0while high != 0 or cur != 0:if cur == 0: res += high * digitelif cur == 1: res += high * digit + low + 1else: res += (high + 1) * digitlow += cur * digitcur = high % 10high //= 10digit *= 10return res

剑指 Offer 44. 数字序列中某一位的数字

class Solution:def findNthDigit(self, n: int) -> int:digit, start, count = 1, 1, 9while n > count: n -= countstart *= 10digit += 1count = 9 * start * digitnum = start + (n - 1) // digit return int(str(num)[(n - 1) % digit])

剑指 Offer 45. 把数组排成最小的数

class Solution(object):def minNumber(self, nums):strs = [str(num) for num in nums]for i in range(len(strs)):for j in range(len(strs)-1, i, -1):if strs[i]+strs[j] >= strs[j]+strs[i]:strs[i], strs[j] = strs[j], strs[i]return "".join(strs)

剑指 Offer 46. 把数字翻译成字符串

# 动态规划
class Solution:def translateNum(self, num: int) -> int:s = str(num)n = len(s)dp = [1 for _ in range(n + 1)] for i in range(2, n + 1):if  '10'<=s[i - 2:i]<='25':dp[i] = dp[i - 2] + dp[i - 1]else:dp[i] = dp[i - 1]return dp[n]

剑指 Offer 47. 礼物的最大价值

class Solution:def maxValue(self, grid: List[List[int]]) -> int:m, n = len(grid), len(grid[0])for j in range(1, n): # 初始化第一行grid[0][j] += grid[0][j - 1]for i in range(1, m): # 初始化第一列grid[i][0] += grid[i - 1][0]for i in range(1, m):for j in range(1, n):grid[i][j] += max(grid[i][j - 1], grid[i - 1][j])return grid[-1][-1]

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

class Solution:def lengthOfLongestSubstring(self, s: str) -> int:dic, res, i = {}, 0, -1for j in range(len(s)):if s[j] in dic:i = max(dic[s[j]], i) # 更新左指针 idic[s[j]] = j # 哈希表记录res = max(res, j - i) # 更新结果return res

剑指 Offer 49. 丑数

class Solution:def nthUglyNumber(self, n: int) -> int:dp, a, b, c = [1] * n, 0, 0, 0for i in range(1, n):n2, n3, n5 = dp[a] * 2, dp[b] * 3, dp[c] * 5dp[i] = min(n2, n3, n5)if dp[i] == n2: a += 1if dp[i] == n3: b += 1if dp[i] == n5: c += 1return dp[-1]

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

class Solution:def firstUniqChar(self, s: str) -> str:dic = {}for c in s:dic[c] = not c in dicfor c in s:if dic[c]: return creturn ' '

剑指 Offer 51. 数组中的逆序对

class Solution:def mergeSort(self, nums, tmp, l, r):if l >= r:return 0mid = (l + r) // 2inv_count = self.mergeSort(nums, tmp, l, mid) + self.mergeSort(nums, tmp, mid + 1, r)i, j, pos = l, mid + 1, lwhile i <= mid and j <= r:if nums[i] <= nums[j]:tmp[pos] = nums[i]i += 1inv_count += (j - (mid + 1))else:tmp[pos] = nums[j]j += 1pos += 1for k in range(i, mid + 1):tmp[pos] = nums[k]inv_count += (j - (mid + 1))pos += 1for k in range(j, r + 1):tmp[pos] = nums[k]pos += 1nums[l:r+1] = tmp[l:r+1]return inv_countdef reversePairs(self, nums: List[int]) -> int:n = len(nums)tmp = [0] * nreturn self.mergeSort(nums, tmp, 0, n - 1)

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

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:A, B = headA, headBwhile A != B:A = A.next if A else headBB = B.next if B else headAreturn A

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

class Solution:def search(self, nums: List[int], target: int) -> int:def helper(tar):i, j = 0, len(nums) - 1while i <= j:m = (i + j) // 2if nums[m] <= tar: i = m + 1else: j = m - 1return ireturn helper(target) - helper(target - 1)

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

class Solution:def missingNumber(self, nums: List[int]) -> int:i, j = 0, len(nums) - 1while i <= j:m = (i + j) // 2if nums[m] == m: i = m + 1else: j = m - 1return i

剑指 Offer 54. 二叉搜索树的第k大节点

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def kthLargest(self, root: TreeNode, k: int) -> int:def dfs(root):if not root: returndfs(root.right)if self.k == 0: returnself.k -= 1if self.k == 0: self.res = root.valdfs(root.left)self.k = kdfs(root)return self.res

剑指 Offer 55 - I. 二叉树的深度

# DFS解法
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def maxDepth(self, root: TreeNode) -> int:if not root: return 0return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
# BFS解法
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def maxDepth(self, root: TreeNode) -> int:if not root: return 0queue, res = [root], 0while queue:tmp = []for node in queue:if node.left: tmp.append(node.left)if node.right: tmp.append(node.right)queue = tmpres += 1return res

剑指 Offer 55 - II. 平衡二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def isBalanced(self, root: TreeNode) -> bool:def recur(root):if not root: return 0left = recur(root.left)if left == -1: return -1right = recur(root.right)if right == -1: return -1return max(left, right) + 1 if abs(left - right) <= 1 else -1return recur(root) != -1

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

class Solution:def singleNumbers(self, nums: List[int]) -> List[int]:x, y, n, m = 0, 0, 0, 1for num in nums:         # 1. 遍历异或n ^= numwhile n & m == 0:        # 2. 循环左移,计算 mm <<= 1       for num in nums:         # 3. 遍历 nums 分组if num & m: x ^= num # 4. 当 num & m != 0else: y ^= num       # 4. 当 num & m == 0return x, y              # 5. 返回出现一次的数字

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

class Solution:def singleNumber(self, nums: List[int]) -> int:return (3*sum(list(set(nums)))-sum(nums))//2

剑指 Offer 57. 和为s的两个数字

class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:i, j = 0, len(nums) - 1while i < j:if nums[i] > target- nums[j]: j -= 1elif nums[i] < target - nums[j]: i += 1else: return nums[i], nums[j]return []

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

class Solution:def findContinuousSequence(self, target: int) -> List[List[int]]:i, j, s, res = 1, 2, 3, []while i < j:if s == target:res.append(list(range(i, j + 1)))if s >= target:s -= ii += 1else:j += 1s += jreturn res

剑指 Offer 58 - I. 翻转单词顺序

class Solution:def reverseWords(self, s: str) -> str:return ' '.join(s.strip().split()[::-1])

剑指 Offer 58 - II. 左旋转字符串

# 字符串切片
class Solution:def reverseLeftWords(self, s: str, n: int) -> str:return s[n:] + s[:n]
# 列表遍历拼接
class Solution:def reverseLeftWords(self, s: str, n: int) -> str:res = []for i in range(n, n + len(s)):res.append(s[i % len(s)])return ''.join(res)

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

class Solution:def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:if not nums or k == 0: return []n = len(nums)q = collections.deque()for i in range(k):while q and nums[i] >= nums[q[-1]]:q.pop()q.append(i)ans = [nums[q[0]]]for i in range(k, n):while q and nums[i] >= nums[q[-1]]:q.pop()q.append(i)while q[0] <= i - k:q.popleft()ans.append(nums[q[0]])return ans

剑指 Offer 59 - II. 队列的最大值

import queueclass MaxQueue:def __init__(self):self.queue = queue.Queue()self.deque = queue.deque()def max_value(self) -> int:return self.deque[0] if self.deque else -1def push_back(self, value: int) -> None:self.queue.put(value)while self.deque and self.deque[-1] < value:self.deque.pop()self.deque.append(value)def pop_front(self) -> int:if self.queue.empty(): return -1val = self.queue.get()if val == self.deque[0]:self.deque.popleft()return val# Your MaxQueue object will be instantiated and called as such:
# obj = MaxQueue()
# param_1 = obj.max_value()
# obj.push_back(value)
# param_3 = obj.pop_front()

剑指 Offer 60. n个骰子的点数

class Solution:def dicesProbability(self, n: int) -> List[float]:dp = [1.0 / 6.0] * 6for i in range(2, n + 1):tmp = [0] * (5 * i + 1)for j in range(len(dp)):for k in range(6):tmp[j + k] += dp[j] / 6dp = tmpreturn dp

剑指 Offer 61. 扑克牌中的顺子

class Solution:def isStraight(self, nums: List[int]) -> bool:joker = 0nums.sort() # 数组排序for i in range(4):if nums[i] == 0: joker += 1 # 统计大小王数量elif nums[i] == nums[i + 1]: return False # 若有重复,提前返回 falsereturn nums[4] - nums[joker] < 5 # 最大牌 - 最小牌 < 5 则可构成顺子

剑指 Offer 62. 圆圈中最后剩下的数字

class Solution:def lastRemaining(self, n: int, m: int) -> int:x = 0for i in range(2, n + 1):x = (x + m) % ireturn x

剑指 Offer 63. 股票的最大利润

class Solution:def maxProfit(self, prices: List[int]) -> int:cost, profit = float("+inf"), 0for price in prices:cost = min(cost, price)profit = max(profit, price - cost)return profit

剑指 Offer 64. 求1+2+…+n

class Solution:def __init__(self):self.res = 0def sumNums(self, n: int) -> int:n > 1 and self.sumNums(n - 1)self.res += nreturn self.res
class Solution:def sumNums(self, n: int) -> int:return n!=0 and (n + self.sumNums(n-1))

剑指 Offer 65. 不用加减乘除做加法

class Solution:def add(self, a: int, b: int) -> int:x = 0xffffffffa, b = a & x, b & xwhile b != 0:a, b = (a ^ b), (a & b) << 1 & xreturn a if a <= 0x7fffffff else ~(a ^ x)

剑指 Offer 66. 构建乘积数组

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

剑指 Offer 67. 把字符串转换成整数

class Solution:def strToInt(self, str: str) -> int:str = str.strip()                      # 删除首尾空格if not str: return 0                   # 字符串为空则直接返回res, i, sign = 0, 1, 1int_max, int_min, bndry = 2 ** 31 - 1, -2 ** 31, 2 ** 31 // 10if 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': return int_max if sign == 1 else int_min # 数字越界处理res = 10 * res + ord(c) - ord('0') # 数字拼接return sign * res

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

# 迭代解法
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':if p.val > q.val: p, q = q, p # 保证 p.val < q.valwhile root:if root.val < p.val: # p,q 都在 root 的右子树中root = root.right # 遍历至右子节点elif root.val > q.val: # p,q 都在 root 的左子树中root = root.left # 遍历至左子节点else: breakreturn root
# 递归解法
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':if root.val < p.val and root.val < q.val:return self.lowestCommonAncestor(root.right, p, q)if root.val > p.val and root.val > q.val:return self.lowestCommonAncestor(root.left, p, q)return root

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

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:if not root or root == p or root == q: return rootleft = self.lowestCommonAncestor(root.left, p, q)right = self.lowestCommonAncestor(root.right, p, q)if not left and not right: return if not left: return right if not right: return left return root

Python版剑指Offer题解相关推荐

  1. java计算整数出现的次数_[剑指offer题解][Java]1到n整数中1出现的次数

    前言 众所周知,<剑指offer>是一本"好书". 如果你是个算法菜鸡(和我一样),那么最推荐的是先把剑指offer的题目搞明白. 对于剑指offer题解这个系列,我的 ...

  2. 对分查找的最多次数_「剑指offer题解」数组中出现次数超过一半的数字

    关注我--个人公众号:后端技术漫谈 我目前是一名后端开发工程师.主要关注后端开发,数据安全,网络爬虫,物联网,边缘计算等方向. 原创博客主要内容 Java知识点复习全手册 Leetcode算法题解析 ...

  3. java queue 最大值_[剑指offer题解]队列的最大值/滑动窗口的最大值

    前言 众所周知,<剑指offer>是一本"好书". 为什么这么说? 因为在技术面试中,它里面罗列的算法题在面试中出现的频率是非常非常高的. 有多高,以我目前不多的面试来 ...

  4. java 最大子数组_[剑指offer题解][Java]连续子数组的最大和

    前言 众所周知,<剑指offer>是一本"好书". 如果你是个算法菜鸡(和我一样),那么最推荐的是先把剑指offer的题目搞明白. 对于剑指offer题解这个系列,我的 ...

  5. 【剑指offer题解】二维数组中的查找

    前言 众所周知,对于面试而言,<剑指offer>是一本"好书". 如果你和我一样是个算法菜鸡,那么最推荐的是先把剑指offer的题目搞明白,其次再去刷LeetCode等 ...

  6. Java算法:牛客网Java版剑指Offer全套算法面试题目整理及电子档,Java算法与数据结构面试题,面试刷题、背题必备!牛客网剑指offer

    剑指offer(java版) 牛客网Java版剑指Offer全套题目67道 资源来源于网络 目录 1.二维数组中的查找 2.替换空格 3.从尾到头打印链表 4.重建二叉树 5.用两个栈实现队列 6.旋 ...

  7. JS版剑指offer

    JS版剑指offer JS刷题总结 牛客网 递归算法的时间复杂度:递归的总次数*每次递归的数量. 递归算法的空间复杂度:递归的深度*每次递归创建变量的个数. 二叉树(12道): 剑指Offer(4): ...

  8. C++版 - 剑指Offer 面试题36:数组中的逆序对及其变形(Leetcode 315. Count of Smaller Numbers After Self)题解

    剑指Offer 面试题36:数组中的逆序对 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 例如, 在数组{7,5, ...

  9. C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解

    剑指offer 面试题39:判断平衡二叉树 提交网址:  http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...

  10. 【剑指offer】【leetcode精选题集】【Java】剑指offer题解合集 更新中

    Leetcode题集 [剑指offer][JAVA]面试题第[03]题[数组中的重复数字][HashSet] [剑指offer][JAVA]面试题第[04]题[二维数中的查找][数组] [剑指offe ...

最新文章

  1. Java 对象和类 的理解
  2. 上struts2的xml在lt;result type=quot;redirectquot;gt;参数问题
  3. 标题栏外区域拖动窗体
  4. SAP Commerce SmartEdit 如何同 SAP Spartacus 协同工作
  5. Java中的Redis的思维导图_Redis思维导图
  6. REVERSE-COMPETITION-NEPCTF
  7. vue 每次弹框都初始化
  8. LA 3523 圆桌骑士
  9. HbuliderX 历史版本下载
  10. SQL服务器引擎组件概览
  11. 20172331 《Java程序设计》第3周学习总结
  12. 汇编调用C函数--利用堆栈传递参数
  13. ARM处理器系统初始化编程注意事项
  14. TI DSP 28335 自学之路,到此止步
  15. linux _max_path,[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?...
  16. 服务器系统2008r2网卡驱动,防吞Win 7/xp/10/server2008 r2网络驱动(网卡驱动)
  17. android自动生成cardview,CardView
  18. DCFNET:用于视觉跟踪的判别相关滤波器网络
  19. 苹果回应巴西政府禁止销售不附赠充电器的iPhone;小米造车新进展;国内首家以数据服务为核心的央企数据中台上线 | EA周报...
  20. pthon3+itchat微信机器人,自定义回复,定时发送晚安,微信小号控制,信息群发功能,获取位置

热门文章

  1. SSM+jsp整合步骤(注解开发)
  2. Qt Design Studio 1.4正式发布
  3. 马云为何学计算机,IT大佬高考:李彦宏是状元 马云数学仅1分
  4. 国外cpa广告联盟EMU-lead-cpa联盟详解(2)im搭建
  5. 自动化软件测试工作内容,「自动化测试」自动化测试岗位职责(职位描述,任职要求)...
  6. Android 音乐资源管理与播放
  7. C语言如何实现寻找峰值函数,findpeaks 寻找峰值函数
  8. 北斗产业有哪些“芯”优势
  9. 深度学习学习笔记——keras中的verbose
  10. 微软服务器操作系统后门,Windows操作系统后门