二叉树:以为使用了递归,其实还隐藏着回溯
本文 https://github.com/youngyangyang04/leetcode-master 已经收录,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图,可以fork到自己仓库,有空看一看一定会有所收获,如果对你有帮助也给一个star支持一下吧!
昨天的总结篇中还在玩耍的你,该总结啦!(本周小结之二叉树),有两处问题需要说明一波。
求相同的树
还在玩耍的你,该总结啦!(本周小结之二叉树)中求100.相同的树的代码中,我笔误贴出了 求对称树的代码了,细心的同学应该都发现了。
那么如下我再给出求100. 相同的树 的代码,如下:
class Solution {
public:bool compare(TreeNode* tree1, TreeNode* tree2) {if (tree1 == NULL && tree2 != NULL) return false;else if (tree1 != NULL && tree2 == NULL) return false;else if (tree1 == NULL && tree2 == NULL) return true;else if (tree1->val != tree2->val) return false; // 注意这里我没有使用else// 此时就是:左右节点都不为空,且数值相同的情况// 此时才做递归,做下一层的判断bool compareLeft = compare(tree1->left, tree2->left); // 左子树:左、 右子树:左bool compareRight = compare(tree1->right, tree2->right); // 左子树:右、 右子树:右bool isSame = compareLeft && compareRight; // 左子树:中、 右子树:中(逻辑处理)return isSame;}bool isSameTree(TreeNode* p, TreeNode* q) {return compare(p, q);}
};
以上的代码相对于:二叉树:我对称么? 仅仅修改了变量的名字(为了符合判断相同树的语境)和 遍历的顺序。
大家应该会体会到:认清判断对称树本质之后, 对称树的代码 稍作修改 就可以直接用来AC 100.相同的树。
递归中隐藏着回溯
在二叉树:找我的所有路径?中我强调了本题其实是用到了回溯的,并且给出了第一个版本的代码,把回溯的过程充分的提现了出来。
如下的代码充分的体现出回溯:(257. 二叉树的所有路径)
class Solution {
private:void traversal(TreeNode* cur, vector<int>& path, vector<string>& result) {path.push_back(cur->val);// 这才到了叶子节点if (cur->left == NULL && cur->right == NULL) {string sPath;for (int i = 0; i < path.size() - 1; i++) {sPath += to_string(path[i]);sPath += "->";}sPath += to_string(path[path.size() - 1]);result.push_back(sPath);return;}if (cur->left) {traversal(cur->left, path, result);path.pop_back(); // 回溯}if (cur->right) {traversal(cur->right, path, result);path.pop_back(); // 回溯}}public:vector<string> binaryTreePaths(TreeNode* root) {vector<string> result;vector<int> path;if (root == NULL) return result;traversal(root, path, result);return result;}
};
如下为精简之后的递归代码:(257. 二叉树的所有路径)
class Solution {
private:void traversal(TreeNode* cur, string path, vector<string>& result) {path += to_string(cur->val); // 中if (cur->left == NULL && cur->right == NULL) {result.push_back(path);return;}if (cur->left) traversal(cur->left, path + "->", result); // 左 回溯就隐藏在这里if (cur->right) traversal(cur->right, path + "->", result); // 右 回溯就隐藏在这里}public:vector<string> binaryTreePaths(TreeNode* root) {vector<string> result;string path;if (root == NULL) return result;traversal(root, path, result);return result;}
};
上面的代码,大家貌似感受不到回溯了,其实回溯就隐藏在traversal(cur->left, path + “->”, result);中的 path + “->”。 每次函数调用完,path依然是没有加上"->" 的,这就是回溯了。
为了把这份精简代码的回溯过程展现出来,大家可以试一试把:
if (cur->left) traversal(cur->left, path + "->", result); // 左 回溯就隐藏在这里
改成如下代码:
path += "->";
traversal(cur->left, path, result); // 左
即:
if (cur->left) {path += "->";traversal(cur->left, path, result); // 左
}
if (cur->right) {path += "->";traversal(cur->right, path, result); // 右
}
此时就没有回溯了,这个代码就是通过不了的了。
如果想把回溯加上,就要 在上面代码的基础上,加上回溯,就可以AC了。
if (cur->left) {path += "->";traversal(cur->left, path, result); // 左path.pop_back(); // 回溯path.pop_back();
}
if (cur->right) {path += "->";traversal(cur->right, path, result); // 右path.pop_back(); // 回溯path.pop_back();
}
大家应该可以感受出来,如果把 path + "->"
作为函数参数就是可以的,因为并有没有改变path的数值,执行完递归函数之后,path依然是之前的数值(相当于回溯了)
如果有点遗忘了,建议把这篇二叉树:找我的所有路径?在仔细看一下,然后再看这里的总结,相信会豁然开朗。
这里我尽量把逻辑的每一个细节都抠出来展现了,希望对大家有所帮助!
我是程序员Carl,利用工作之余重刷leetcode,更多精彩算法文章尽在:代码随想录,关注后,回复「Java」「C++」「python」「简历模板」等等,有我整理多年的学习资料,可以加我微信,备注「简单自我介绍」+「组队刷题」,拉你进入刷题群(无任何广告,纯个人分享),每天一道经典题目分析,我选的每一道题目都不是孤立的,而是由浅入深一脉相承的,如果跟住节奏每篇连续着看,定会融会贯通。
以下资料希望对你有帮助:
- 学习资料以及我的开源项目
- 我的B站视频:算法和编程语言的讲解
- leetcode刷题攻略
- 程序员应该如何写简历(附简历模板)
- 一线互联网公司技术面试的流程以及注意事项
- C++面试&C++学习指南知识点整理
如果感觉题解对你有帮助,不要吝啬给一个
链接 https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/ 思路 本题和113.路径总和II是类似的思路,做完这道题,可以顺便把113. ... 二叉树递归遍历存在的问题 如果我们的二叉树只有左子树,而且树的高度还很深的时候,这个时候递归调用遍历的时候,栈帧空间开辟的较大,很可能造成栈溢出.但是我们一个程序中,为堆分配的空间要比栈大的多,这个时 ... 二叉树的几种递归和非递归式遍历: 1 #include <fstream> 2 #include <iostream> 3 4 using namespace std; 5 6 ... 引文 大部分教材给出了 线索二叉树的中序递归线索化以及中序遍历,但是没给出非递归,现在网上大部分非递归算法代码各种条件判断写的比较离谱,所以干脆自己总结了一个清晰的.线索二叉树中序非递归线索化以及递归 ... 理论基础 二叉树的定义形式有:节点指针和数组 在数组中,父节点的下标为i,那么其左孩子的下标即i*2+1,右孩子的下标即为i*2+2 二叉树的常见遍历形式有:前序遍历.后序遍历.中序遍历和层序遍历 前 ... >数据结构:typedef struct BINODE{TELEMETYPE data;struct BINODE *lchild,*rchild;}BiNode,*BiTtree;>递归 ... 二叉树的遍历 (递归实现) 用C++实现二叉树的"先根遍历"存储. 用C++实现二叉树的"先根遍历"."中根遍历"."后根遍历&q ... 二叉树的遍历 目录 递归遍历 非递归遍历 Morris遍历 1. 递归遍历 递归版遍历只要当前节点不为null,就可以三次回到当前节点. public static void preOrderRecu ... #二叉树的特点: 每一个节点最多有两棵子树,所以二叉树中不存在度大于2的节点,注意,是最多有两棵,没有也是可以的 左子树和右子树是有顺序的,次序不能颠倒,这点可以在哈夫曼编码中体现, 顺序不同编码方式 ... 数据结构(六)二叉树的遍历(递归非递归方法) 一.递归方法 1.先序遍历 void PreOrder(BiTree T) {visit(T);PreOrder(T->LChild)PreOrde ...二叉树:以为使用了递归,其实还隐藏着回溯相关推荐
最新文章
热门文章