提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
国庆假期结束!开始工作!
一、题目
路径总和 II
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]
示例 2:
输入:root = [1,2,3], targetSum = 5
输出:[]
示例 3:
输入:root = [1,2], targetSum = 0
输出:[]
提示
树中节点总数在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
二、思路
一眼dfs 但是对于终止条件和结束条件的判断需要结合题意格外注意:
注意,必须是根结点到叶子结点,也就是说完成状态必须是root的左右孩子均为None,且数值成立的情况
注意,值有可能为负值,所以无法判断结束状态
三、代码
# 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: Optional[TreeNode], targetSum: int) -> List[List[int]]:
result=[]
def dfs(root,path,currentSum):
if(root.left ==None and root.right==None and currentSum == targetSum): #终止状态
result.append(path[:])
return
#递归+回溯
if(root.left): #左孩子
path.append(root.left.val)
dfs(root.left,path,currentSum+root.left.val)
path.pop()
if(root.right): #右孩子
path.append(root.right.val)
dfs(root.right,path,currentSum+root.right.val)
path.pop()
return
#根结点存在
if(root !=None ):
dfs(root,[root.val],root.val)
return result
else:
return []
四、题目
二叉树展开为链表
给你二叉树的根结点 root ,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。
示例
示例 1:
输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [0]
输出:[0]
提示
树中结点数在范围 [0, 2000] 内
-100 <= Node.val <= 100
进阶
你可以使用原地算法(O(1) 额外空间)展开这棵树吗?
五、思路
1、空间复杂度O(n)
先对它进行先序遍历,每次记录遍历中的上一个结点~但前序遍历需要用递归实现,也就是需要消耗栈的空间,空间复杂度并不是O(1)
第一步,转换为左节点的单链表,以防止数据丢失 ; 第二步,转换为右节点
2、空间复杂度O(1)
但如果想要O(1)空间复杂度,就需要精准找到每个结点的右子树的前驱结点。
首先,对于每一个结点A来说,因为我们的目的是把目标元素挪到A的右孩子位置,因此要先把A的右孩子的位置空出来。结点A右孩子(也就是右子树的根结点)的前一个元素一定是结点A左子树的最右节点(root.right到最后的结点),因此对A的左子树进行遍历找到这个结点,并把A的右子树接在其后,然后此时A的右孩子已经空出,可以把左孩子接上了。再看下一个结点,也就是A的右孩子,有无左孩子,如果有的话仍按前面的操作一遍即可,直至所有节点都没左孩子。
六、代码
1、空间复杂度O(n)
# 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 flatten(self, root: Optional[TreeNode]) -> None:
"""
Do not return anything, modify root in-place instead.
"""
last_root=[TreeNode()]
def root_first_traval(root):
if(root == None): #空
return
last_root[0].left=root #操作
last_root[0]=root #更改上一个结点
root_first_traval(root.left)
root_first_traval(root.right)
root_first_traval(root)
while(root != None):
root.right=root.left
root.left=None
root=root.right
return root
2.空间复杂度O(1)
# 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 flatten(self, root: Optional[TreeNode]) -> None:
"""
Do not return anything, modify root in-place instead.
"""
def find(root):
while(root.right): #先找到最右子树
root=root.right
return root
while(root !=None):
if(root.left != None): #有左子树
find(root.left).right=root.right #右孩子空出来
root.right=root.left #左孩子接上去
root.left=None #左孩子删去
root=root.right
return root