LeetCode 112. 路徑總和 、113. 路徑總和 II 思考分析

目錄

  • 112. 路徑總和
    • 題目
    • 遞歸解
    • 遞歸解,其他人的解法
    • 迭代解,其他人的解法
  • 113. 路徑總和 II
    • 題目
    • 遞歸解
    • 遞歸解,參考別人的思路

112. 路徑總和

題目

給定一個二叉樹和一個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等于目標和。

說明: 葉子節點是指沒有子節點的節點。

示例:
給定如下二叉樹,以及目標和 sum = 22,
在這里插入圖片描述
返回 true, 因為存在目標和為 22 的根節點到葉子節點的路徑 5->4->11->2。

遞歸解

1、函數參數:當前樹的根結點、當前累積的路徑和,目標路徑和;返回值為空
2、終止條件:該結點為空
3、單層邏輯:如果該結點不為空,則在累積路徑和上加上該結點的值。如果該結點是葉子結點,判斷此時的累積路徑和與目標路徑和是否相同,如果相同則將全局變量ifHas改為true,認為能夠找到路徑和為目標值的路徑。然后返回父結點,回溯到上一個狀態,參數會自動更正為上一個狀態的參數。接下來就是按順序對該結點的左右孩子進行遍歷

這個思路是有問題的,因為它只在葉子結點之后才回溯,這是不合理的,但是也能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;//如果是葉子結點,則進行比較if(cur->left==NULL && cur->right==NULL){//如果和目標結果相同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、函數參數、返回值確定
之前有個結論:如果需要搜索整棵二叉樹,那么遞歸函數就不要返回值,如果要搜索其中一條符合條件的路徑,遞歸函數就需要返回值,因為遇到符合條件的路徑就要及時返回
本題并不需要遍歷整棵樹,所以遞歸函數需要返回值,可以用bool類型表示。

bool traversal(TreeNode* cur,int count)		

2、終止條件確定
在如何統計一條路徑和的方法上,代碼隨想錄使用遞減的方法,讓計數器count初始為目標和,然后每次減去遍歷路徑結點上的數值。如果最后count==0,同時到了葉子結點的話,說明了找到目標和。如果遍歷到了葉子結點,cout不為0,就是沒找到

if(!cur->left && !cur->right && count == 0) return true;		//遇到葉子結點,并且計數為0
if(!cur->left && !cur->right) return false;					//遇到葉子結點,沒有找到合適的邊,直接返回

3、確定單層遞歸的邏輯
因為終止條件是判斷也自己誒單,所以遞歸過程中就不要讓空結點進入遞歸了。
遞歸函數的返回值為true的話說明了找到了合適的路徑,應該立刻返回

if(cur->left)
{count -=cur->left->val;//遇到葉子結點返回true,則直接返回true;if(traversal(cur->left,count)) return true;count +=cur->left->val;			//回溯,撤銷處理結果
}
if(cur->right)
{count -=cur->right->val;//遇到葉子結點返回true,則直接返回true;if(traversal(cur->right,count)) return true;count +=cur->right->val;			//回溯,撤銷處理結果
}
return false;
class Solution {
public:bool traversal(TreeNode* cur,int count)		{if(!cur->left && !cur->right && count == 0) return true;		//遇到葉子結點,并且計數為0if(!cur->left && !cur->right) return false;					//遇到葉子結點,沒有找到合適的邊,直接返回if(cur->left){count -=cur->left->val;//遇到葉子結點返回true,則直接返回true;if(traversal(cur->left,count)) return true;count +=cur->left->val;			//回溯,撤銷處理結果}if(cur->right){count -=cur->right->val;//遇到葉子結點返回true,則直接返回true;if(traversal(cur->right,count)) return true;count +=cur->right->val;			//回溯,撤銷處理結果}return false;}bool hasPathSum(TreeNode* root, int sum) {if(root == NULL) return false;return traversal(root,sum-root->val);}
};

迭代解,其他人的解法

如果使用棧模擬遞歸的話對于回溯如何處理?
此時棧里面的一個元素不僅要記錄該結點指針,還要記錄從頭結點到該結點的路徑數值總和。
這里使用pair結構來存放棧里面的元素。(第一次用這個結構)
定義為:

pair<TreeNode*,int> pair<結點指針,路徑數值>

為棧中的一個元素。
使用棧模擬前序遍歷;

/*** 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 hasPathSum(TreeNode* root, int sum) {if(root == NULL) return false;//此時棧里面要放的是pair<結點指針,路徑數值>stack<pair<TreeNode*,int>> st;st.push(pair<TreeNode*,int>(root,root->val));while(!st.empty()){pair<TreeNode*,int> node = st.top();st.pop();//如果這個結點是葉子結點,同時該結點的路徑數值等于sum,那么就返回trueif(!node.first->left &&!node.first->right && sum == node.second ) return true;//右結點,壓進去一個結點的時候,將該結點的路徑數值也記錄下來if(node.first->right){st.push(pair<TreeNode*,int>(node.first->right,node.second+node.first->right->val));}//右結點,壓進去一個結點的時候,將該結點的路徑數值也記錄下來if(node.first->left){st.push(pair<TreeNode*,int>(node.first->left,node.second+node.first->left->val));}}return false;}
};

113. 路徑總和 II

題目

給定一個二叉樹和一個目標和,找到所有從根節點到葉子節點路徑總和等于給定目標和的路徑。

說明: 葉子節點是指沒有子節點的節點。
在這里插入圖片描述

遞歸解

同樣的道理,Mysum作為函數參數每次返回的時候會自動更正,不需要手動回溯。
完成一次子結果,就將子結果送入paths中。
path需要手動回溯。

 path.push_back(cur->left->val);traversal(cur->left,target,Mysum);path.pop_back();

同時需要注意,在一開始要將根結點送入path中,因為在我們的遞歸函數中只對左右孩子進行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;}  //如果是葉子結點,則進行比較if(cur->left==NULL && cur->right==NULL){//如果和目標結果相同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;//遞歸函數不需要返回值,因為我們要遍歷整個樹void traversal(TreeNode* cur,int count){if(!cur->left && !cur->right && count == 0)     //遇到了葉子結點且找到了和為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;}
};

工程實踐上一定要clear,但是由于力扣后臺測試數據,每次都是新new一個對象

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/377968.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377968.shtml
英文地址,請注明出處:http://en.pswp.cn/news/377968.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

kotlin 查找id_Kotlin程序查找矩陣的轉置

kotlin 查找idA transpose of a matrix is simply a flipped version of the original matrix. We can transpose a matrix by switching its rows with its columns 矩陣的轉置只是原始矩陣的翻轉形式。 我們可以通過切換矩陣的行和列來轉置矩陣 Given a matrix, we have to…

[mongodb翻譯]分片和故障轉移

一個配置恰當的mongodb 分片集群不會有單點失效。 本章節描述了集群服務器中可能出現的故障&#xff0c;及相應的對策。 1. 某個mongos路由進程故障 每一個mongos會運行每一臺應用服務器上面&#xff0c;該應用服務器只能通過這個mongos進程和集群進行通信。mongos進程不是…

看張子陽的書真是收獲很多,也醒悟了很多(一)

摘錄&#xff1a; 這是有一次開會時&#xff0c;我的老總跟我們說了這樣一個事例&#xff1a;通常來說&#xff0c;醫生是很高尚的職業&#xff08;暫不考慮國內醫生的負面新聞&#xff09;&#xff0c;尤其是牙科醫生&#xff0c; 他們有著體面的工作并且收入不菲。但是&#…

【C++ grammar】抽象、封裝與this指針

目錄1、Abstraction and Encapsulation&#xff08;抽象與封裝&#xff09;1. Data Field Encapsulation (數據域封裝)2. Accessor and Mutator (訪問器與更改器)2.1. To read/write private data, we need get/set function (為讀寫私有數據&#xff0c;需要get/set函數)2.2. …

java創建臨時文件_用Java創建一個臨時文件

java創建臨時文件The task is to create a temporary file in Java. 任務是用Java創建一個臨時文件。 Creating a temporary file 創建一個臨時文件 To create a temporary file in java – we use createTempFile() method of "File" class. The createTempFile()…

十九、圖像的形態學操作

一、圖像形態學 圖像形態學是圖像處理學科的一個單獨分支學科 主要針對的是灰度圖和二值圖像 是由數學的集合論以及數學中的拓撲幾何原理發展而來 二、膨脹操作&#xff08;dilate&#xff09; 33的卷積核 以33為卷積核從左往右(從上往下)開始運行&#xff0c;若這卷積核…

X名稱空間(WPF)

筆記簡述 閑話x名稱空間簡要x名稱空間的Attributex名稱空間的標簽擴展x名稱空間的XAML指令元素閑話 本筆記參考與《深入淺出WPF》、MSDN、Some Blog… MSDN的飛機票點這里。 x名稱空間簡要 在VS中新建個WpfApplication都會自動生成xmlns:x"http://schemas.microsoft.com/w…

基于Bresenham和DDA算法畫線段

直線&#xff1a;ykxb 為了將他在顯示屏上顯示出來&#xff0c;我們需要為相應的點賦值&#xff0c;那么考慮到計算機的乘法執行效率&#xff0c;我們肯定不會選擇用Ykxb這個表達式求值&#xff0c;然后進行畫線段。 我們應當是將它轉化為加法運算。 下面提供兩種常見的算法&am…

leetcode 106. 從中序與后序遍歷序列構造二叉樹 105. 從前序與中序遍歷序列構造二叉樹思考分析

目錄1、106題目2、參考思路&#xff1a;遞歸切割數組3、105題目4、同樣思路的代碼1、106題目 2、參考思路&#xff1a;遞歸切割數組 代碼參考&#xff1a;公眾號&#xff1a;代碼隨想錄 后序數組中序數組 以 后序數組(左右中)的最后一個元素作為切割點&#xff0c;先切中序數組…

按頻率對元素進行排序

Prerequisite: 先決條件&#xff1a; Hashing data structure 散列數據結構 How to write user-defined comparator for priority queue STL in C? 如何在C 中為優先級隊列STL編寫用戶定義的比較器&#xff1f; How to sort a map based on values instead of value? 如何根…

二十、分水嶺算法

一、基本原理 分水嶺算法主要是基于距離變換&#xff08;distance transform&#xff09;&#xff0c;找到mark一些種子點&#xff0c;從這些種子點出發根據像素梯度變化進行尋找邊緣并標記 分水嶺&#xff1a;可以簡單的理解成一座山&#xff0c;然后來洪水了&#xff0c;水開…

細數WOW里暴雪的“親兒子”們

. 不知何時&#xff0c;魔獸世界的詞匯中忽然出現了一個新玩意&#xff1a;親兒子。雖說這個稱呼現在大多是拿來調侃法爺的&#xff0c;但江山代有兒子出&#xff0c;各領風騷一兩天&#xff0c;今天風光無限的法爺們也經歷過被其他職業壓得抬不起頭的小媳婦生涯。那么今天…

Linux下串口ttyS2,ttyS3不能用的問題解決辦法

PC104&#xff0c;Xlinux下&#xff0c;突然發現串口3,4不能用。。。 以為是硬件的問題&#xff0c;換成wince后&#xff0c;3,4工作正常&#xff0c;排除電路問題 在linux下查看dmesg: serial8250: ttyS0 at I/O 0x3f8 (irq 4) is a 16550Aserial8250: ttyS1 at I/O 0x2f8 (i…

安卓log.e函數打印示例_log1p()函數以及C ++中的示例

安卓log.e函數打印示例C log1p()函數 (C log1p() function) log1p() function is a library function of cmath header, it is used to get the natural logarithm (the base-e logarithm) of the one plus given value. It accepts a value (float, double, or long double) …

【C++grammar】C++類數據成員的初始化

目錄1、類成員的就地初始化example2、構造函數初始化3、默認構造函數&#xff1a;Default Constructor4、舉例5、成員的初始化方法的優先級1、類成員的就地初始化example class S { int m 7; // ok, copy-initializes m int n(7); // 錯誤&#xff1a;不允許用小括號初始化…

二十一、人臉檢測

一、識別圖像中的人臉 haarcascade_frontalface_alt_tree.xml lbpcascade_frontalcatface.xml GitHub上有Haar級聯檢測器源代碼可自行下載&#xff0c;lbp級聯檢測器也一樣有源碼可自行下載 也一樣 import cv2 as cv import numpy as npdef face_detect(image):gray cv.cvtC…

aspx特殊符號說明

http://www.cnblogs.com/GnagWang/archive/2010/07/14/1777130.html轉載于:https://www.cnblogs.com/mingyongcheng/archive/2011/11/24/2261253.html

javascript運算符_JavaScript中的按位運算符

javascript運算符JavaScript按位運算符 (JavaScript Bitwise Operators) A lot of times you come across some strange operators where youre knocking your head to understand what is going on in the code. Almost all the programming languages have bitwise operators…

[置頂] Android的IPC訪問控制設計與實現

3.3.1 IPC鉤子函數設計與實現 IPC Binder是Android最重要的進程間通信機制&#xff0c;因此&#xff0c;必須在此實施強制訪問控制。 1. 修改secuirty.h 打開終端shell&#xff0c;輸入指令“cd /android4.0/kernel/goldfish/include/linux/vim security.h”&#xff0c;找到結…

TensorFlow在Anaconda環境下創建

一、我使用的是Anaconda自帶的Jupyter編譯器&#xff0c;詳細的安裝教程可以參考博文 二、之后打開Jupyter 三、進行測試 我的tensorflow使用的是2.0版本 import tensorflow.compat.v1 as tf tf.disable_v2_behavior()a tf.constant([1.0,2.0],name"a") b tf.co…