LeetCode Easy 437 路徑之和III Python
Disscusion Method
演算法:雜湊表+DFS
思路:
首先要想暴力解法是怎樣進行的
在暴力解法中,也就是下面我的那種解法,遍歷每一個節點,在每一個節點的位置,還要向下遍歷其他的每一個節點
但是這樣的話在遍歷的過程中有很多遍歷是重複的
10
/ \
5 -3
/ \ \
3 2 11
/ \ \
3 -2 1
比如遍歷到5的時候。會有5->3->3,3->3,10->5->3->3,其實就是一條路徑,只不過每次的節點不一樣罷了。
但是用暴力解法遍歷的話會重複遍歷很多次,例如以10開頭的時候遍歷了10->5->3->3,後面又會以5開頭遍歷5->3->3
所以首先要想的是,如何將一條路徑拆成多條,因為根據題意,答案的路徑不一定非要是從root開始的,所以在遍歷
過程中形成的path路徑,能不能將他拆開?比如從10開始遍歷,遍歷路徑10->5->3,能不能將其拆成10,5->3?
答案當然是可以的,因為可以看做是從10出發了3層到達的這裡,其實第一層10的時候就可以記錄下來這個10,然後到
10->5->3的時候,再"減去"前面單個節點10的情況就好了。
所以這種解法就是基於這樣的思想在遍歷所有節點。並且聯想TwoSum中的做法,用雜湊表來儲存要找的那個"加數"
注意到本題中,要求的解的路徑其實可以看做是一整條路徑中的一部分,然後再根據上面講到的將一條路徑拆成多個
部分組成。那麼就可以設定一個雜湊表,record,由record記錄當前路徑和的個數,{curr_sum:counter},
由curr_sum來記錄遍歷到當前節點的路徑和,如果一條目標路徑在這條路徑中,那麼就可以按上述的拆分路徑的方法求得
當前子路徑的前序路徑和,即prefix_sum = curr_sum - target,然後在record中查詢prefix_sum的個數。如果record
中記錄了這個prefix_sum,那麼就表明當前路徑中包含解,並且prefix_sum有幾個,這樣的路徑就有幾個
如:10->5->3,target = 8,curr_sum - 8 = 10,而前面記錄下來的record[10]=1,就說明有1條包含答案的路徑,
當然了,如果前面record[10]=n,那麼就說明走到了10->5->3時,在這條路徑上符合答案的路徑就有n條,result += n
所以在遍歷的過程中應該record[curr_sum] += 1,記錄下來curr_sum的個數,curr_sum在後面層數的遞迴中就相當於
是prefix_sum了。
所以根據以上思路dfs前序遍歷二叉樹,並且要注意的是當前節點的左右子樹遍歷完之後,要record[curr_sum] -= 1
因為記錄record[curr_sum] -= 1是為了記錄當前路徑和作為prefix的話有多少個,當前節點的子樹遍歷完之後,應該
彈出當前節點的路徑和,就像回溯的時候一樣。比如還是10->5->3這裡,記錄了18後,遍歷完這個③的節點,將18的個數減1,
避免遞迴到⑩的右子樹時,可能某個位置需要前面是18,但是誤認為左子樹的③這裡記錄的18是符合要求的,這樣會將路徑
計算錯。
❗️❗️❗️所以要明確,record[curr_sum]記錄的是當前路徑上有多少個子字首路徑的和是curr_sum,或者從子遞迴中看,應該叫
record[prefix_sum]
複雜度分析:
時間:ON,遍歷一遍所有節點
空間:ON,雜湊表空間
def pathSum(self, root, sum):
self.result = 0
def dfs(root, record, curr_sum):
if root == None:
return
curr_sum += root.val
prefix_sum = curr_sum - sum
if prefix_sum in record:
self.result += record[prefix_sum]
record.setdefault(curr_sum, 0)
record[curr_sum] += 1
dfs(root.left, record, curr_sum)
dfs(root.right, record, curr_sum)
record[curr_sum] -= 1
dfs(root, {0: 1}, 0)
return self.result
def pathSum1(self, root, sum):
"""
My Brute Force Method
演算法:暴力
思路:
Do as they say
遍歷所有可能,dfs遍歷每個節點,在每個節點位置向下深度遍歷calculateSum()計算是否構成題解
這裡主要是會重複計算一些路徑和,導致時間的浪費
複雜度分析:
時間:ON2
空間:ON2
"""
self.counter = 0
def calculateSum(root,path_sum):
if root == None :
return
path_sum += root.val
if path_sum == sum:
self.counter += 1
calculateSum(root.left,path_sum)
calculateSum(root.right,path_sum)
def dfs(root):
if root == None:
return
calculateSum(root,0)
dfs(root.left)
dfs(root.right)
dfs(root)
return self.counter