Offer 32 Ⅱ 从上到下打印二叉树 Ⅱ
Grade : easy
代码展示:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if root is None:
return []
Queue = [root] # 预添加根节点
res = [] # 记录遍历的值
while Queue: # 遍历当前层的节点
res.append([node.val for node in Queue]) # 当前层作为单独的一个列表添加到res
level = [] # 用来记录下一层的节点,循环一次更新一次
for node in Queue: # 开始遍历当前层的节点
if node.left:
level.append(node.left)
if node.right:
level.append(node.right)
# 循环结束,Queue内的节点更新为下一层的节点
Queue = level
return res
思路:就是一个(简单)的循环结构,主要思路在注释中做了展示。主体方法为:广度优先搜索
- 首先根元素入队
- 当队列不为空的时候
- 求当前队列的长度 s_isi
- 依次从队列中取 s_isi 个元素进行拓展,然后进入下一次迭代
运行结果展示:
官方参考代码:
class 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
相比之下代码简洁了许多,在处理size时避免了其数值变化(for循环中只会执行一次初始化,但是在条件判断那块由于poll()导致size()改变了)
如果用
for(int i = 0; i < q.size(); i++)
例如q.size()长度为3,那么
- 第一次:i = 0,长度3,i++
- 第二次:i = 1,长度2,i++
- 第三次:i = 2,长度1,此次本应该进循环但是没有进去。
用图示方法,for循环里的i只能初始化一次,也就是i = 3,2,1,刚好三次。
Q 221 Maximal Square
Grade: normal
代码展示:
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
m, n = len(matrix), len(matrix[0])
dp = [[0]*n for _ in range(m)]
for i in range(m):
for j in range(n):
if i==0 or j==0:
dp[i][j] = int(matrix[i][j])
else:
if matrix[i][j] == '1':
dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1
side = max(max(dp[i][j] for j in range(n)) for i in range(m))
return side*side
思路:
和计算二维矩阵内正方形的个数思路一致
暴力解法:设当前遍历的i,ji,j位置为矩形的右下角,则其可能产生的最大正方形的边长可能为min(i,j)min(i,j),如果一个个判断该正方形是否全为1,整体的时间复杂度为O(m*n*min(m,n))O(m∗n∗min(m,n)),这还是在判定正方形全为O(1)O(1)的时间复杂度为1的条件下(这需要借助二维前缀和的辅助数组)
但是这样做忽略了以i,j为正方形右下角顶点与其相邻正方形的关系
注意最终返回的是正方形的面积
运行结果展示:
官方参考代码:
class Solution:
def getWidth(self,num): #步骤3:求一个数中连续最多的1
w=0
while num>0:
num&=num<<1
w+=1
return w
def maximalSquare(self, matrix: List[List[str]]) -> int:
nums=[int(''.join(n),base=2) for n in matrix] #步骤1:每一行当作二进制数
res,n=0,len(nums)
for i in range(n): #步骤2:枚举所有的组合,temp存储相与的结果
temp=nums[i]
for j in range(i,n):
temp&=nums[j]
if self.getWidth(temp)<j-i+1:
break
res=max(res,j-i+1)
return res*res
怎么感觉我的方法更暴力)相比耗时更短,其中有一个比较特殊的点:
当某一行与后面行相与的时候,1 的个数只可能变少,即宽度只会越变越小,当宽度(连续1的个数)小于高度的时候,会以宽度作为正方形的边长,此时高度再增加已经没有意义了,因为不可能再有最大值产生了,所以可以跳出循环,直接开始遍历下一个 start 行
Q 1502 Can Make Arithmetic Progression From Sequence
Grade: easy
代码展示:
class Solution:
def canMakeArithmeticProgression(self, arr: List[int]) -> bool:
arr.sort()
a=arr[1]-arr[0]
if all(arr[i]-arr[i-1]==a for i in range(1,len(arr))):
return True
return False
2.0版本
class Solution:
def canMakeArithmeticProgression(self, arr: List[int]) -> bool:
arr.sort()
return len(set([arr[i]-arr[i-1] for i in range(1,len(arr))])) == 1
(实际上就越是写法不同
思路:
随到了个super 简单的,就是冒泡法排序加等差数列任意两差为一个定常数
运行结果展示:
官方参考代码:
class Solution:
def canMakeArithmeticProgression(self, arr: List[int]) -> bool:
arr.sort()
for i in range(1, len(arr) - 1):
if arr[i] * 2 != arr[i - 1] + arr[i + 1]:
return False
return True
几乎完全一致好嘛,没什么好分析的