LeetCode 112. 路径总和 、113. 路径总和 II 思考分析
目錄
- 112. 路徑總和
- 題目
- 遞歸解
- 遞歸解,其他人的解法
- 迭代解,其他人的解法
- 113. 路徑總和 II
- 題目
- 遞歸解
- 遞歸解,參考別人的思路
112. 路徑總和
題目
給定一個(gè)二叉樹(shù)和一個(gè)目標(biāo)和,判斷該樹(shù)中是否存在根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑,這條路徑上所有節(jié)點(diǎn)值相加等于目標(biāo)和。
說(shuō)明: 葉子節(jié)點(diǎn)是指沒(méi)有子節(jié)點(diǎn)的節(jié)點(diǎn)。
示例:
給定如下二叉樹(shù),以及目標(biāo)和 sum = 22,
返回 true, 因?yàn)榇嬖谀繕?biāo)和為 22 的根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑 5->4->11->2。
遞歸解
1、函數(shù)參數(shù):當(dāng)前樹(shù)的根結(jié)點(diǎn)、當(dāng)前累積的路徑和,目標(biāo)路徑和;返回值為空
2、終止條件:該結(jié)點(diǎn)為空
3、單層邏輯:如果該結(jié)點(diǎn)不為空,則在累積路徑和上加上該結(jié)點(diǎn)的值。如果該結(jié)點(diǎn)是葉子結(jié)點(diǎn),判斷此時(shí)的累積路徑和與目標(biāo)路徑和是否相同,如果相同則將全局變量ifHas改為true,認(rèn)為能夠找到路徑和為目標(biāo)值的路徑。然后返回父結(jié)點(diǎn),回溯到上一個(gè)狀態(tài),參數(shù)會(huì)自動(dòng)更正為上一個(gè)狀態(tài)的參數(shù)。接下來(lái)就是按順序?qū)υ摻Y(jié)點(diǎn)的左右孩子進(jìn)行遍歷
這個(gè)思路是有問(wèn)題的,因?yàn)樗辉谌~子結(jié)點(diǎn)之后才回溯,這是不合理的,但是也能AC。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:bool ifHas=false;void traversal(TreeNode* cur,int target,int Mysum){if(cur==NULL) return;if(cur!=NULL) Mysum+=cur->val;//如果是葉子結(jié)點(diǎn),則進(jìn)行比較if(cur->left==NULL && cur->right==NULL){//如果和目標(biāo)結(jié)果相同if(Mysum == target) ifHas=true;return;}if(cur->left){traversal(cur->left,target,Mysum);}if(cur->right){traversal(cur->right,target,Mysum);}return ;}bool hasPathSum(TreeNode* root, int sum) {//if(root == NULL) return false;int Mysum=0;traversal(root,sum,Mysum);return ifHas;} };遞歸解,其他人的解法
1、函數(shù)參數(shù)、返回值確定
之前有個(gè)結(jié)論:如果需要搜索整棵二叉樹(shù),那么遞歸函數(shù)就不要返回值,如果要搜索其中一條符合條件的路徑,遞歸函數(shù)就需要返回值,因?yàn)橛龅椒蠗l件的路徑就要及時(shí)返回。
本題并不需要遍歷整棵樹(shù),所以遞歸函數(shù)需要返回值,可以用bool類(lèi)型表示。
2、終止條件確定
在如何統(tǒng)計(jì)一條路徑和的方法上,代碼隨想錄使用遞減的方法,讓計(jì)數(shù)器count初始為目標(biāo)和,然后每次減去遍歷路徑結(jié)點(diǎn)上的數(shù)值。如果最后count==0,同時(shí)到了葉子結(jié)點(diǎn)的話(huà),說(shuō)明了找到目標(biāo)和。如果遍歷到了葉子結(jié)點(diǎn),cout不為0,就是沒(méi)找到
3、確定單層遞歸的邏輯
因?yàn)榻K止條件是判斷也自己誒單,所以遞歸過(guò)程中就不要讓空結(jié)點(diǎn)進(jìn)入遞歸了。
遞歸函數(shù)的返回值為true的話(huà)說(shuō)明了找到了合適的路徑,應(yīng)該立刻返回
迭代解,其他人的解法
如果使用棧模擬遞歸的話(huà)對(duì)于回溯如何處理?
此時(shí)棧里面的一個(gè)元素不僅要記錄該結(jié)點(diǎn)指針,還要記錄從頭結(jié)點(diǎn)到該結(jié)點(diǎn)的路徑數(shù)值總和。
這里使用pair結(jié)構(gòu)來(lái)存放棧里面的元素。(第一次用這個(gè)結(jié)構(gòu))
定義為:
pair<TreeNode*,int> pair<結(jié)點(diǎn)指針,路徑數(shù)值>
為棧中的一個(gè)元素。
使用棧模擬前序遍歷;
113. 路徑總和 II
題目
給定一個(gè)二叉樹(shù)和一個(gè)目標(biāo)和,找到所有從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)路徑總和等于給定目標(biāo)和的路徑。
說(shuō)明: 葉子節(jié)點(diǎn)是指沒(méi)有子節(jié)點(diǎn)的節(jié)點(diǎn)。
遞歸解
同樣的道理,Mysum作為函數(shù)參數(shù)每次返回的時(shí)候會(huì)自動(dòng)更正,不需要手動(dòng)回溯。
完成一次子結(jié)果,就將子結(jié)果送入paths中。
path需要手動(dòng)回溯。
同時(shí)需要注意,在一開(kāi)始要將根結(jié)點(diǎn)送入path中,因?yàn)樵谖覀兊倪f歸函數(shù)中只對(duì)左右孩子進(jìn)行push_back()
class Solution { public:vector<vector<int>> paths;vector<int> path;void traversal(TreeNode* cur,int target,int Mysum){if(cur==NULL) return;if(cur!=NULL){Mysum+=cur->val;} //如果是葉子結(jié)點(diǎn),則進(jìn)行比較if(cur->left==NULL && cur->right==NULL){//如果和目標(biāo)結(jié)果相同if(Mysum == target){paths.push_back(path);}return;}if(cur->left){path.push_back(cur->left->val);traversal(cur->left,target,Mysum);path.pop_back();}if(cur->right){path.push_back(cur->right->val);traversal(cur->right,target,Mysum);path.pop_back();}return ;}vector<vector<int>> pathSum(TreeNode* root, int sum) {if(root==NULL) return {};int Mysum=0;path.push_back(root->val);traversal(root,sum,Mysum);return paths;} };遞歸解,參考別人的思路
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { private:vector<vector<int>> paths;vector<int> path;//遞歸函數(shù)不需要返回值,因?yàn)槲覀円闅v整個(gè)樹(shù)void traversal(TreeNode* cur,int count){if(!cur->left && !cur->right && count == 0) //遇到了葉子結(jié)點(diǎn)且找到了和為sum的路徑{paths.push_back(path);return;}if(!cur->left && !cur->right ) return;if(cur->left){path.push_back(cur->left->val);count-=cur->left->val;traversal(cur->left,count);count+=cur->left->val;path.pop_back();}if(cur->right){path.push_back(cur->right->val);count-=cur->right->val;traversal(cur->right,count);count+=cur->right->val;path.pop_back();}return;} public:vector<vector<int>> pathSum(TreeNode* root, int sum) {paths.clear();path.clear();if(root==NULL) return paths;path.push_back(root->val);traversal(root,sum-root->val);return paths;} };工程實(shí)踐上一定要clear,但是由于力扣后臺(tái)測(cè)試數(shù)據(jù),每次都是新new一個(gè)對(duì)象
總結(jié)
以上是生活随笔為你收集整理的LeetCode 112. 路径总和 、113. 路径总和 II 思考分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。