1261 在受污染的二叉树中查找元素
层次遍历修改数据,用集合保存数据
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class FindElements:
def __init__(self, root: TreeNode):
self.root=root
self.root.val=0
node=self.root
#list保存数据最慢
#使用set快一点
self.hash=set()
#self.hash={}
stack=[node]
while stack:
for _ in range(len(stack)):
node=stack.pop(0)
self.hash.add(node.val)
#self.hash[node.val]=1
if node.left:
node.left.val=2*node.val+1
stack.append(node.left)
if node.right:
node.right.val=2*node.val+2
stack.append(node.right)
def find(self, target: int) -> bool:
if target in self.hash:
return True
return False
# Your FindElements object will be instantiated and called as such:
# obj = FindElements(root)
# param_1 = obj.find(target)
递归更快:
class FindElements:
def __init__(self, root: TreeNode):
self.root=root
self.root.val=0
node=self.root
self.hash=set()
def dfs(root,val):
if not root:
return
#val值在上一层已经被计算好了
root.val=val
self.hash.add(val)
dfs(root.left,2*val+1)
dfs(root.right,2*val+2)
dfs(node,0)
def find(self, target: int) -> bool:
if target in self.hash:
return True
return False
1017. 负二进制转换
与2进制表示法类似,当能够整除的时候该位为0,否则为1.
只是需要修改一下除数的迭代公式,正常二进制的商向下取整,负二进制商向上取整(使用math.ceil)
Math.ceil() 函数返回大于或等于一个给定数字的最小整数
import math
class Solution:
def baseNeg2(self, N: int) -> str:
if N==0:
return '0'
# N是十进制数,x是负进制
def num_to_n_scale(N, x):
buff = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 'A', 'B', 'C', 'D', 'E', 'F']
res=''
while N!=0:
s=math.ceil(N/x) #商
y=N-s*x #余数
res=str(buff[y])+res
N=s
return res
return num_to_n_scale(N,-2)
面试题26 树的子结构
class Solution:
def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
if not A or not B:
return False
#判断以A为根节点的子树是否与B相同
def recur(A,B):
if not B:
return True
if not A or A.val!=B.val:
return False
if A.val==B.val:
return recur(A.left,B.left) and recur(A.right,B.right)
#需要遍历A的所有节点作为根节点的子树,是否存在与B相同结构
return recur(A,B) or self.isSubStructure(A.left,B) or self.isSubStructure(A.right,B)
669. 修剪二叉搜索树
class Solution:
def trimBST(self, root: TreeNode, L: int, R: int) -> TreeNode:
if not root:
return
#根节点改变的两种情况
if root.val<L:
#修剪后的根节点一定出自右子树
return self.trimBST(root.right,L,R)
#修剪后的根节点一定出自左子树
elif root.val>R:
return self.trimBST(root.left,L,R)
#当前根节点符合要求,根节点不变,递归判断左子树和右子树
root.left=self.trimBST(root.left,L,R)
root.right=self.trimBST(root.right,L,R)
return root
226. 翻转二叉树
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:
return
stack=[root]
while stack:
for _ in range(len(stack)):
node=stack.pop(0)
node.left,node.right=node.right,node.left
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
return root
二叉树中使用全局变量计算结果
1372 二叉树中的最长交错路径
递归 DFS
class Solution:
def longestZigZag(self, root: TreeNode) -> int:
self.maxium=0
#我们只需要传递「当前」这个点应该走的方向(「向左」或者「向右」)dir,以及以这个点结尾的最长交错路径的长度 len
# 0向左,1向右
#lent是root为结尾的最长交错路径
# direction 是当前点应该走的方向
def dfs(root,direction,lent):
if not root:
return
self.maxium=max(self.maxium,lent)
if direction==0:
#如果当前点应该向左且可以向左,那么就让他向左走一步,新的 len 是当前的 len 加一
dfs(root.left,1,lent+1)
#如果只有右子树,则只能向右,则长度重置为1,
dfs(root.right,0,1)
else:
dfs(root.right,0,lent+1)
dfs(root.left,1,1)
#root中没有父节点,所以长度初始化为0
dfs(root,0,0)
dfs(root,1,0)
return self.maxium
动态规划 BFS
class Solution:
def longestZigZag(self, root: TreeNode) -> int:
if not root:
return 0
#记 f(u)为从根到节点 u 的路径上以 u 结尾并且 u 是它父亲的左儿子的最长交错路径,g(u) 为从根到节点 u 的路径上以 u 结尾并且 u 是它父亲的右儿子的最长交错路径。
f,g=defaultdict(int),defaultdict(int)
stack=deque()
stack.append((root,None))
f[root],g[root]=0,0
maxium=0
while stack:
for _ in range(len(stack)):
node,pre=stack.popleft()
if pre:
if node==pre.left:
g[node]=f[pre]+1
else:
f[node]=g[pre]+1
if node.left:
stack.append((node.left,node))
if node.right:
stack.append((node.right,node))
for _,maxf in f.items():
maxium=max(maxium,maxf)
for _ , maxg in g.items():
maxium=max(maxium,maxg)
return maxium
814 二叉树剪枝
python中函数里引用,树是不能直接整棵树级别的=none的 这样不会修改原变量(对象),只有修改子树或结点的值是会影响到root的,所以在判断完这个子树要删除最好返回一个标记,再上一层rode.left/right = None是可以修改到原变量的,所以题解也是改子树而不是传进来的整棵树
class Solution:
def pruneTree(self, root: TreeNode) -> TreeNode:
# 包含1 返回True
# 不包含1,则返回False,且将不满足条件的子树置空
def dfs(root):
if not root:
return False
flagf=dfs(root.left)
flagr=dfs(root.right)
if not flagf:
root.left=None
if not flagr:
root.right=None
return root.val==1 or flagf or flagr
if dfs(root):
return root
else:
return None
1123 最深叶节点的最近公共祖先
同865
我们可以看出最近公共祖先的两个子树是等高的,如果不等高,那么高度较小的那个子树叶结点必然不是最深。
我们可以设计这样的深度优先搜索算法,每一层返回值有两部分组成:一部分是以该结点为根的子树中,最深叶结点的公共祖先,另一部分是该层的高度(也即该结点到其最深叶结点的深度)
class Solution:
def lcaDeepestLeaves(self, root: TreeNode) -> TreeNode:
def dfs(root):
if not root:
return None,0
#公共祖先,当前节点作为根节点的子树最大深度
l,ld=dfs(root.left)
r,rd=dfs(root.right)
#左右子树深度相同,说明该点为最深叶节点的最近公共祖先
if ld==rd:
return root,ld+1
elif ld<rd:
return r,rd+1
else:
return l,ld+1
node,depth=dfs(root)
return node
865. 具有所有最深结点的最小子树
class Solution:
def subtreeWithAllDeepest(self, root: TreeNode) -> TreeNode:
def dfs(root):
if not root:
return 0,None
left,lr=dfs(root.left)
right,rr=dfs(root.right)
if left==right:
return left+1,root
elif left<right:
return right+1,rr
else:
return left+1,lr
depth,node=dfs(root)
return node
验证是否是二叉搜索树:
面试题 04.05
98
迭代:
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
if not root:
return True
stack=[]
node=root
pre=float('-inf')
while stack or node:
while node:
stack.append(node)
node=node.left
node=stack.pop()
if node.val<=pre:
return False
pre=node.val
node=node.right
return True
递归:
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
if not root:
return True
def dfs(node,left,right):
if not node:
return True
if left<node.val<right:
return dfs(node.left,left,node.val) and dfs(node.right,node.val,right)
return False
return dfs(root,float('-inf'),float('inf'))
面试题 34 二叉树中和为某一值的路径
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
self.hash=defaultdict(list)
def dfs(root,res,sumval):
if not root:
return None
#到达根节点时,将该路径的和及对应路径加入到哈希表中
if not root.left and not root.right:
self.hash[sumval+root.val].append(res+[root.val])
#不到叶子结点,则继续向左向右遍历
dfs(root.left,res+[root.val],sumval+root.val)
dfs(root.right,res+[root.val],sumval+root.val)
dfs(root,[],0)
return self.hash[sum]
卡特兰数:
96 不同的二叉搜索树:
class Solution:
def numTrees(self, n: int) -> int:
if n==0:return 1
## dp[i]:以1..i为节点组成的二叉搜索树的个数
dp=[0]*(n+1)
dp[0],dp[1]=1,1
for i in range(2,n+1):
for j in range(i):
dp[i]+=dp[j]*dp[i-j-1]
return dp[n]
N对括号正确匹配数目
面试题 08.09 括号
在匹配过程中不能出现剩余左括号数目多于剩余右括号
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
#p是剩余( 的个数,q是剩余)的个数
res=[]
def dfs(p,q,ans):
# 如果剩下的左括号比右括号多,则匹配不成功
if p>q:
return
if p==0 and q==0:
res.append(ans)
#优先匹配左括号
if p>0:
dfs(p-1,q,ans+'(')
if q>0:
dfs(p,q-1,ans+')')
dfs(n,n,'')
return res
n=3:
字符串加法:乘法2
43 字符串相乘
class Solution:
def multiply(self, num1: str, num2: str) -> str:
if num1=='0' or num2=='0':
return '0'
n1=len(num1)
n2=len(num2)
res=[0]*(n1+n2)
#将对应位数乘积保存到数组中
for i in range(n1-1,-1,-1):
for j in range(n2-1,-1,-1):
#字符转换成数字
cur=(ord(num1[i])-ord('0'))*(ord(num2[j])-ord('0'))
res[i+j]+=cur//10 #商
res[i+j+1]+=cur%10 #余数
for i in range(n1+n2-1,-1,-1):
flag=res[i]//10
res[i-1]+=flag
res[i]=res[i]%10
return ''.join([str(i) for i in res]).lstrip('0')
415 字符串相加
class Solution:
def addStrings(self, num1: str, num2: str) -> str:
if num1=='0' and num2=='0':
return '0'
n=max(len(num1),len(num2))
num1=num1.rjust(n,'0')
num2=num2.rjust(n,'0')
res=[0]*(n+1)
i=n-1
while i>=0:
cur=ord(num1[i])-ord('0')+ord(num2[i])-ord('0')
res[i]+=cur//10
res[i+1]+=cur%10
i-=1
for i in range(n,-1,-1):
flag=res[i]//10
res[i-1]+=flag
res[i]=res[i]%10
return ''.join([str(i) for i in res]).lstrip('0')
2.两数相加
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
root=ListNode(0)
tmp=root
flag=0
while l1 or l2:
x=l1.val if l1 else 0
y=l2.val if l2 else 0
cur=x+y+flag
tmp.next=ListNode(cur%10)
flag=cur//10
if l1:l1=l1.next
if l2:l2=l2.next
tmp=tmp.next
if flag==1:
tmp.next=ListNode(flag)
return root.next
445 两数相加二
数据入栈,从前往后构造链表
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
stack1,stack2=[],[]
root=ListNode(0)
tmp=root
while l1 or l2:
if l1:
stack1.append(l1.val)
l1=l1.next
if l2:
stack2.append(l2.val)
l2=l2.next
res=[]
flag=0
while stack1 or stack2:
x=stack1.pop() if stack1 else 0
y=stack2.pop() if stack2 else 0
cur=x+y+flag
flag=cur//10
res.append(cur%10)
res.append(flag)
if res[-1]==0:
res=res[:-1]
for i in res[::-1]:
tmp.next=ListNode(i)
tmp=tmp.next
return root.next
从后往前构造链表
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
stack1,stack2=[],[]
root=ListNode(0)
tmp=root
while l1 or l2:
if l1:
stack1.append(l1.val)
l1=l1.next
if l2:
stack2.append(l2.val)
l2=l2.next
res=[]
flag=0
ans=None
while stack1 or stack2 or flag!=0:
x=stack1.pop() if stack1 else 0
y=stack2.pop() if stack2 else 0
cur=x+y+flag
flag=cur//10
#从后往前构造链表
cur=ListNode(cur%10)
cur.next=ans
ans=cur
return ans