- 剑指 Offer 04. 二维数组中的查找
-
- 矩阵中战斗力最弱的 K 行
- 剑指 Offer 14- I. 剪绳子
- 剑指 Offer 14- II. 剪绳子 II
- 剑指 Offer 13. 机器人的运动范围
- 剑指 Offer 12. 矩阵中的路径
- 剑指 Offer 32 - I. 从上到下打印二叉树
- 剑指 Offer 32 - II. 从上到下打印二叉树 II
- 剑指 Offer 32 - III. 从上到下打印二叉树 III
剑指 Offer 04. 二维数组中的查找
将二维数组看成一个二叉搜索树,根是左下角的点,左分支小,右分支大,中序遍历是递增的。因此每次对比节点和目标值的大小,如果小了就往右边去,列增加,如果大了就往左边去,行减少。
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
i = len(matrix)-1
j = 0
while i >= 0 and j < len(matrix[0]):
if matrix[i][j] < target:
j += 1
elif matrix[i][j] > target:
i -= 1
else:return True
return False
从右上角开始搜索也是可以的,但是当遇到输入为[] ,target=0时会报错,因为matrix[0]会报错index超了。
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
i = 0
j = len(matrix[0])-1
while j >= 0 and i < len(matrix):
if matrix[i][j] > target:
j -= 1
elif matrix[i][j] < target:
i += 1
else:return True
return False
1337. 矩阵中战斗力最弱的 K 行
每日一题
class Solution:
def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
m, n = len(mat), len(mat[0]) # m是行,n是列数
power = list()
for i in range(m):
l, r, pos = 0, n - 1, -1
while l <= r:
mid = (l + r) // 2
if mat[i][mid] == 0:
r = mid - 1
else:
pos = mid
l = mid + 1
power.append((pos + 1, i))
heapq.heapify(power) # 将列表转换为堆
ans = list()
for i in range(k):
ans.append(heapq.heappop(power)[1]) #从堆中返回弹出最小item的第二个元素(就是前面存入的行)
return ans
剑指 Offer 14- I. 剪绳子
n = 2, 1+1
n = 3, 1+2
n = 4, 2+2
n = 5, 3+2
n = 6, 3+3
n = 7, 3+4 = 3+2+2 先剪成长度为3的绳子,一直到<=4就剪成长度为2的
n = 8, 3+3+2
class Solution:
def cuttingRope(self, n: int) -> int:
if n <= 3:
return n-1
res = 1
while n >= 2:
if n<=4:
return res*n
n -= 3
res*=3
剑指 Offer 14- II. 剪绳子 II
动态规划解法。
class Solution:
def cuttingRope(self, n: int) -> int:
if n <= 3:
return n-1
dp=[0 for _ in range(n+1)]
dp[1] = 1
dp[2] = 2
dp[3] = 3
for i in range(4, n+1):
for j in range(i-1):
dp[i] = max(dp[j]*dp[i-j], dp[i])
return dp[n]%1000000007
剑指 Offer 13. 机器人的运动范围
class Solution:
def movingCount(self, m: int, n: int, k: int) -> int:
def dfs(i,j):
summ = i//10 + i%10 + j//10+j%10
if 0<=i<m and 0<=j<n and summ<= k and (i,j) not in visited: # 防止重复走
visited.add((i,j))
return 1+dfs(i+1,j)+dfs(i,j+1)
else:return 0
visited = set()
return dfs(0,0)
剑指 Offer 12. 矩阵中的路径
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
m = len(board)
n = len(board[0])
visited=[[0 for _ in range(n)]for _ in range(m)]
for i in range(m):
for j in range(n):
if board[i][j]==word[0]:
visited[i][j] = 1
if self.backtrace(i, j, visited,board, word[1:]):
return True
else:visited[i][j]=0
return False
def backtrace(self, i,j,visited,board,word):
if len(word) == 0:
return True
for i0,j0 in [[i+1,j], [i-1,j], [i,j+1], [i,j-1]]:
if 0 <= i0 < len(board) and 0 <= j0 < len(board[0]) and board[i0][j0] == word[0]:
if visited[i0][j0]:
continue
else:
visited[i0][j0]=1
if self.backtrace(i0, j0, visited,board, word[1:]):
return True
else:
visited[i0][j0]=0
return False
剑指 Offer 32 - I. 从上到下打印二叉树
bfs广度优先搜索,按层从左往右搜索
class Solution:
def levelOrder(self, root: TreeNode) -> List[int]:
if not root:
return []
ans = []
q = collections.deque() # 双向队列,也可以直接用list
q.append(root)
while q:
node = q.popleft() # node=q.pop(0) 如果用list的话
ans.append(node.val)
if node.left:q.append(node.left)
if node.right:q.append(node.right)
return ans
剑指 Offer 32 - II. 从上到下打印二叉树 II
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
q = collections.deque()
ans=[]
tmp = []
q.append(root)
while q:
tmp = []
for _ in range(len(q)): # 多一层循环,因为这里要按层存入ans
node = q.popleft()
tmp.append(node.val)
if node.left: q.append(node.left)
if node.right: q.append(node.right)
ans.append(tmp)
return ans
剑指 Offer 32 - III. 从上到下打印二叉树 III
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
q = collections.deque()
ans=[]
tmp = []
q.append(root)
count = 1
while q:
tmp = []
for _ in range(len(q)): # 多一层循环,因为这里要按层存入ans
node = q.popleft()
tmp.append(node.val)
if node.left: q.append(node.left)
if node.right: q.append(node.right)
if count%2 == 0:
tmp.reverse() # 偶数层反转一下该层元素
ans.append(tmp)
count += 1
return ans
也可以用deque在队头插入,实现反向
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
q = collections.deque()
ans=[]
tmp = []
q.append(root)
while q:
tmp = collections.deque() #数据类型变成双向队列了
for _ in range(len(q)): # 多一层循环,因为这里要按层存入ans
node = q.popleft()
if len(ans)%2: #偶数层
tmp.appendleft(node.val) # 在左边插入
else:
tmp.append(node.val) #奇数层在右边,队尾插入
if node.left: q.append(node.left)
if node.right: q.append(node.right)
ans.append(list(tmp))# tmp要转换成list,才能被加入ans
return ans