日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[二叉树]二叉树中和为某一值的路径 (剑指offer24)

發(fā)布時間:2023/12/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [二叉树]二叉树中和为某一值的路径 (剑指offer24) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

輸入一棵二叉樹和一個整數(shù),打印出二叉樹中節(jié)點值的和為輸入整數(shù)的所有路徑。從樹的根節(jié)點開始往下一直到葉節(jié)點所經(jīng)過的節(jié)點形成一條路徑。

?

解題思路:


本問題是典型的二叉樹方案搜索問題,使用回溯法解決,其包含 先序遍歷 + 路徑記錄 兩部分。

先序遍歷: 按照 “根、左、右” 的順序,遍歷樹的所有節(jié)點。
路徑記錄: 在先序遍歷中,記錄從根節(jié)點到當(dāng)前節(jié)點的路徑。當(dāng)路徑為 ① 根節(jié)點到葉節(jié)點形成的路徑 且 ② 各節(jié)點值的和等于目標(biāo)值 sum 時,將此路徑加入結(jié)果列表。

?

算法流程:
pathSum(root, sum) 函數(shù):

初始化: 結(jié)果列表 res ,路徑列表 path 。
返回值: 返回 res 即可。
recur(root, tar) 函數(shù):

遞推參數(shù): 當(dāng)前節(jié)點 root ,當(dāng)前目標(biāo)值 tar 。
終止條件: 若節(jié)點 root 為空,則直接返回。
遞推工作:
路徑更新: 將當(dāng)前節(jié)點值 root.val 加入路徑 path ;
目標(biāo)值更新: tar = tar - root.val(即目標(biāo)值 tar 從 sum 減至 00 );
路徑記錄: 當(dāng) ① root 為葉節(jié)點 且 ② 路徑和等于目標(biāo)值 ,則將此路徑 path 加入 res 。
先序遍歷: 遞歸左 / 右子節(jié)點。
路徑恢復(fù): 向上回溯前,需要將當(dāng)前節(jié)點從路徑 path 中刪除,即執(zhí)行 path.pop() 。

?

復(fù)雜度分析:
時間復(fù)雜度 O(N)?: N?為二叉樹的節(jié)點數(shù),先序遍歷需要遍歷所有節(jié)點。
空間復(fù)雜度 O(N)?: 最差情況下,即樹退化為鏈表時,path 存儲所有樹節(jié)點,使用 O(N)額外空間。
代碼:
值得注意的是,記錄路徑時若直接執(zhí)行 res.append(path) ,則是將 path 對象加入了 res ;后續(xù) path 改變時, res 中的 path 對象也會隨之改變。

正確做法:res.append(list(path)) ,相當(dāng)于復(fù)制了一個 path 并加入到 res 。

# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = Noneclass Solution:def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:res, path = [], []# 先序遍歷:根左右def recur(root, target):if not root:returnpath.append(root.val)target -= root.val# 找到路徑if target == 0 and not root.left and not root.right:res.append(list(path)) # 復(fù)制了一個 path 加入到 res 中,這樣修改 path 不影響 resrecur(root.left, target)recur(root.right, target)# 向上回溯,需要刪除當(dāng)前節(jié)點path.pop()recur(root, sum)return res

?

深度優(yōu)先搜索。使用前序遍歷,使用兩個全局變量result和tmp,result來存放最終結(jié)果,tmp用來存放臨時結(jié)果。

每次遍歷,我們先把root的值壓入tmp,然后判斷當(dāng)前root是否同時滿足:

  • 與給定數(shù)值相減為0;
  • 左子樹為空;
  • 右子樹為空。

如果滿足條件,就將tmp壓入result中,否則,依次遍歷左右子樹。需要注意的是,遍歷左右子樹的時候,全局變量tmp是不清空的,直到到了根結(jié)點才請空tmp。

# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution:# 返回二維列表,內(nèi)部每個列表表示找到的路徑def FindPath(self, root, expectNumber):# write code hereif not root:return []if not root.left and not root.right and expectNumber == root.val:return [[root.val]]res = []left = self.FindPath(root.left, expectNumber-root.val)right = self.FindPath(root.right, expectNumber-root.val)for i in left+right:res.append([root.val]+i)return res

?

?

在做這一題之前,我們先來看看怎么輸出二叉樹的從根結(jié)點到每個葉子節(jié)點的路徑。

# 遞歸解法 class TreeNode:def __init__(self, value):self.val = valueself.left = Noneself.right = Noneclass Solution:def binaryTreePaths(self, root):if root == None:return []result = []self.DFS(root, result, [root.val])return resultdef DFS(self, root, result, path):if root.left == None and root.right == None:result.append(path)if root.left != None:self.DFS(root.left, result, path + [root.left.val])if root.right != None:self.DFS(root.right, result, path + [root.right.val]) # 非遞歸解法class TreeNode:def __init__(self, value):self.val = valueself.left = Noneself.right = Noneclass Solution2:def binaryTreePaths2(self, root):if root == None:return []result = []stack = []stack.append((root, [root.val]))while stack:node, path = stack.pop()if node.left == None and node.right == None:result.append(path)if node.left != None:stack.append((node.left, path + [node.left.val]))if node.right != None:stack.append((node.right, path + [node.right.val]))return result

現(xiàn)在再來看這一題,就會發(fā)現(xiàn):其實這一題就是引出所有的從根結(jié)點到葉子結(jié)點的路徑的變形,就在判斷條件上多了一個 sum(path) == self.sums。所以,解法如下:

# 方法一:遞歸 class TreeNode:def __init__(self, x):self.val = xself.left = Noneself.right = Noneclass Solution:# 返回二維列表,內(nèi)部每個列表表示找到的路徑def FindPath(self, root, expectNumber):# write code hereresult = []if root == None:return resultself.sums = expectNumberself.DFS(root, result, [root.val])return resultdef DFS(self, root, result, path):if root.left == None and root.right == None and sum(path) == self.sums:result.append(path)if root.left != None:self.DFS(root.left, result, path + [root.left.val])if root.right != None:self.DFS(root.right, result, path + [root.right.val]) # 方法二:非遞歸 class TreeNode:def __init__(self, x):self.val = xself.left = Noneself.right = Noneclass Solution:# 返回二維列表,內(nèi)部每個列表表示找到的路徑def FindPath(self, root, expectNumber):# write code hereif root == None:return []result = []stack = []stack.append((root, [root.val]))while stack:node, path = stack.pop()if node.left == None and node.right == None and sum(path) == expectNumber:result.append(path)if node.right != None:stack.append((node.right, path + [node.right.val]))if node.left != None:stack.append((node.left, path + [node.left.val]))return result

?

總結(jié)

以上是生活随笔為你收集整理的[二叉树]二叉树中和为某一值的路径 (剑指offer24)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。