1、leetcode113
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
import copy
class Solution(object):
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: List[List[int]]
"""
if not root:
return []
cur =[]
self.res=[]
self.dfs(root,sum,cur)
return self.res
def dfs(self,root,target,cur):
if not root:
return
cur.append(root.val)
if not root.left and not root.right:
if sum(cur) == target:
t = copy.deepcopy(cur)#这边注意的deepcopy,不然cur是不断变化的
self.res.append(t)
return True
else:
return
if root.left:
self.dfs(root.left,target,cur)
cur.pop()
if root.right:
self.dfs(root.right,target,cur)
cur.pop()
用dfs做就挺简单的,注意就是一定是根到叶子节点的路径
2、leetcode236
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
# 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 lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
path1 = self.findpath(root,p,[])
path2 = self.findpath(root,q,[])
#print(path1,path2)
i=0
j=0
while i <len(path1) and j <len(path2):
if path1[i]!=path2[j]:
return path1[i-1]
i+=1
j+=1
if i<len(path1) or j <len(path2):
return path1[j-1]
def findpath(self,root,p,cur):
if not root:
return
cur.append(root)
if root == p:
return cur
if root.left:
if self.findpath(root.left,p,cur):
return cur
cur.pop()
if root.right:
if self.findpath(root.right,p,cur):
return cur
cur.pop()
还是dfs,注意一下
- dfs的时候判断root.left 和root.right非空
- 在最开始遍历根节点之后,要记得在合适的时候(答案不正确时)pop()已经遍历的根节点
3、leetcode114
给定一个二叉树,原地将它展开为链表。
# 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 flatten(self, root):
"""
:type root: TreeNode
:rtype: None Do not return anything, modify root in-place instead.
"""
self.path=[]
self.findpath(root)
for i in range(len(self.path)-1):
self.path[i].left = None
self.path[i].right = self.path[i+1]
def findpath(self,root):
if not root:
return
self.path.append(root)
if root.left:
self.findpath(root.left)
if root.right:
self.findpath(root.right)
我采用的是递归后重置树的左右子树的方法。通过看评论,学到了就地的方法:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def flatten(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
self.dfs(root)
def dfs(self,root):
if not root:
return
tmp = self.dfs(root.right)
root.right = self.dfs(root.left)
root.left = None
cur = root.right
if not cur:
root.right = tmp
else:
while cur.right:
cur = cur.right
cur.right = tmp
return root
4、leetcode199
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
# 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 rightSideView(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
a =[]
a.append(root)
res=[]
last=a[0]
while a:
tmp = a[0]
if tmp.left:
a.append(tmp.left)
if tmp.right:
a.append(tmp.right)
if last ==tmp :
res.append(last.val)
last = a[-1]
a.pop(0)
return res
这个题是要通过层次遍历,找到每层的最后一个节点即可。我的做法是记录一下上一层的最后节点last,通过比较队列头结点和last是否相等,来表明此层是否均遍历完成。当last与当前的队列头结点相同时,说明此时对整层遍历完成,就更新last。
5、
现在你总共有 n 门课需要选,记为 0 到 n-1。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]
给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
if not prerequisites:
return True
degree =[0 for i in range(numCourses)]
q =[]
for i in range(len(prerequisites)):
degree[prerequisites[i][1]] +=1
for i in range(numCourses):
if degree[i]==0:
q.append(i)
for i in q:
for j in range(len(prerequisites)):
if prerequisites[j][0] == i:
degree[prerequisites[j][1]] -=1
if degree[prerequisites[j][1]] == 0:
q.append(prerequisites[j][1])
#print(q)
if len(q)<numCourses:
return False
else:
return True
击败了10%的用户也太真实了。。。因为我这个写的每次都会重新检查prerequisites中所有元素,没有构建当前节点的邻接节点set,一开始我想的是这样构建有点麻烦,但是循环非常耗时。下面是构建了邻接节点set的代码,可以看到有着明显的效率提升。
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
if not prerequisites:
return True
degree =[0 for i in range(numCourses)]
q =[]
dic =[set() for _ in range(numCourses)]
for i in range(len(prerequisites)):
degree[prerequisites[i][1]] +=1
dic[prerequisites[i][0]].add(prerequisites[i][1])
for i in range(numCourses):
if degree[i]==0:
q.append(i)
cnt = 0
while q:
t = q.pop(0)
cnt +=1
for j in dic[t]:
degree[j] -=1
if degree[j] == 0:
q.append(j)
return cnt == numCourses
- 首先下划线表示临时变量,与i作用相同
- 其次这个题用set保存某一节点的子节点,保证得到去重的节点