leetcode题解(二叉树和递归问题)
這篇博客我們主要來看二叉樹和二叉樹問題中使用遞歸來解決問題的思路。這類問題有時思路很簡單,這是因為二叉樹具有天然的遞歸結構,所以我們使用遞歸的解法解決二叉樹有關的問題就變得非常明顯。
二叉樹天然的遞歸結構
- 語義
 - 終止條件
 - 遞歸過程
 
例子
二叉樹前序遍歷
//前序遍歷node節點 void preorder(TreeNode * node){if (node == NULL){ return; //終止條件}cout << node -> val;preorder(node -> left);preorder(node -> right);//遞歸過程 }復制代碼二叉樹查找某個節點
bool contain(Node *node, key key){if (node == NULL)return false;if (key == node->key)return true;if( contain(node -> left,key) || contain(node -> right, key))return true;return false; }復制代碼刪除一顆二叉樹
void destroy(Node * node){if(node == NULL)return;destroy(node->left);destroy(node->right);delete node;count --; }復制代碼leetcode 104. 二叉樹的最大深度
class Solution { public://求節點root的深度int maxDepth(TreeNode* root) {//終止條件if(root == NULL){ return 0;}return 1 + max(maxDepth(root -> left), maxDepth(root -> right));} }; 復制代碼相似問題
leetcode 111
一個簡單的二叉樹問題引發的血案
leetcode 226. 翻轉二叉樹
代碼實現
/// 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:TreeNode* invertTree(TreeNode* root) {if ( root == NULL ) {return NULL;}invertTree( root->left );invertTree( root->right );swap ( root->left, root->right );return root;}};復制代碼相似問題
leetcode 100
leetcode 101
leetcode 222
leetcode 110
注意遞歸的終止條件
有的時候遞歸的終止條件是存在陷阱的。
leetcode 112. 路徑總和
解題思路
采取遞歸來解決這個問題,我們可以從頭結點開始,向它的左右孩子節點尋找sum-根節點的值,不斷向下尋找。這道題陷阱在于終止條件不是node == NULL。
/*** 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;}//為葉子節點if (root -> left == NULL && root -> right == NULL){return root -> val == sum;}return hasPathSum(root -> left, sum - root -> val) || hasPathSum(root -> right, sum - root -> val);return false;} }; 復制代碼定義遞歸問題
我們如何使用遞歸的返回值來解決問題。 函數的語義很重要
leetcode 257. 二叉樹的所有路徑
思路
對于每一個節點,就是該節點的值加上“->”再加上左子樹的路徑字符串和右子樹路徑字符串。當到達葉節點時,將字符串加入結果集。
實現
/*** 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:vector<string> binaryTreePaths(TreeNode* root) {vector<string> res;if (root == NULL){return res;}if (root -> left == NULL && root -> right == NULL){res.push_back(to_string(root -> val));return res;}vector<string> lefts = binaryTreePaths(root -> left);for(int i = 0; i < lefts.size(); i++){res.push_back(to_string(root -> val) + "->" + lefts[i]);}vector<string> rights = binaryTreePaths(root -> right);for(int i = 0; i < rights.size(); i++){res.push_back(to_string(root -> val) + "->" + rights[i]);}return res;} };復制代碼相似問題
leetcode 113
leetcode 129
稍復雜的遞歸邏輯
leetcode 437. 路徑總和 III
解題思路
猛地一看這個描述,和我們之前的Path Sum是一樣的。但是區別在于我們對于路徑的定義不一定要起始于根節點,終止于葉子結點,路徑可以從任意節點開始,但是只能是向下走的。
在一個節點上要通過三個部分獲得答案,第一個部分看看有沒有一條路徑,它包含node這個節點,并且它的和為sum,這個路徑我們進入findPath這個子過程,這個子過程本身又是一個遞歸函數。另外的兩部分就是要在node的左右子樹去尋找沒有這個ndoe節點的值,有沒有這樣的路徑,他們的和仍然為sum,這件事就是我們PathSum這個函數所做的。在node->left和node->right分別調用PathSum的過程中,他們也會調用findPath來求解。
代碼實現
#include <iostream>using namespace std;// 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:// 在以root為根節點的二叉樹中,尋找和為sum的路徑,返回這樣的路徑個數int pathSum(TreeNode* root, int sum) {if ( root == NULL) {return 0;}int res = findPath( root, sum );res += pathSum( root->left, sum );res += pathSum( root->right, sum );return res;}private:// 在以node為根節點的二叉樹中,尋找包含node的路徑,和為sum// 返回這樣的路徑個數int findPath( TreeNode* node, int num){if ( node == NULL ) {return 0;}int res = 0;if ( node->val == num ) {res += 1;}res += findPath( node->left, num - node->val );res += findPath( node->right, num - node->val );return res;}};復制代碼二分搜索樹中的問題
leetcode 235. 二叉搜索樹的最近公共祖先
思路
二分搜索樹:
 每個節點的鍵值大于左孩子
 每個節點的鍵值小于右孩子
 以左右孩子為跟的子樹仍為二分搜索樹
如果我們給的p,q節點都小于node節點,那么他們最近的公共祖先一定在node左邊。如果我們給的p,q節點都大于node節點,那么他們最近的公共祖先一定在ndoe右邊。如果一小一大,那么node一定是最近的公眾祖先。
代碼實現
/*** 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:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {assert(p != NULL && q != NULL);if (root == NULL){return NULL;}if ((root -> val > p -> val) && (root -> val > q -> val))return lowestCommonAncestor(root -> left, p, q);if ((root -> val < p -> val) && (root -> val < q -> val))return lowestCommonAncestor(root -> right, p, q);//p 與q在root的兩側, 則root必為公共祖先,包含p為q的祖先return root;} };復制代碼相似問題
leetcode 98
leetcode 450
leetcode 108
- 中序遍歷
 
leetcode 230
leetcode 236
-------------------------華麗的分割線--------------------
看完的朋友可以點個喜歡/關注,您的支持是對我最大的鼓勵。
個人博客番茄技術小棧和掘金主頁
想了解更多,歡迎關注我的微信公眾號:番茄技術小棧
總結
以上是生活随笔為你收集整理的leetcode题解(二叉树和递归问题)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Date动态获取时间
 - 下一篇: 前端如何识别操作系统