目录
今天我们通过 6 道在leedcode上的题目,来学习一下回溯算法中二叉树中的深搜的相关问题
(下文中的标题都是leedcode对应题目的链接)
leetcode 2331.计算布尔二叉树的值
挺简单的一道题,我们遍历一下左子树,然后再遍历一下右子树,接着根据根节点的值,来决定是 || 还是 && 即可
递归出口就是,当这个节点为叶子节点(因为是完全二叉树,所以有子节点就必定有两个,要么就没有),那么我们直接返回他的值即可
代码如下:
class Solution {
public:
bool evaluateTree(TreeNode* root)
{
if(root->left == nullptr) return root->val;
bool l = evaluateTree(root->left);
bool r = evaluateTree(root->right);
if(root->val == 2) return l || r;
return l && r;
}
};
leetcode 129.求根节点到叶节点数字之和
这道题目,我们直接使用一个变量 n,然后我们每遇到一个节点,我们就将这个节点里面的值加上10倍的n
假设(示例二)我们现在在 9,那么 n 就是4,那么我们往下就传一个49,也就是 n*10 + root->val
当我们碰到根节点的时候,我们直接将加完之后的值返回
上面我们需要用函数来接收,但是因为是值的相加,所以我们直接+=即可
代码如下:
class Solution {
public:
int dfs(TreeNode* root, int n)
{
int ret = 0;
if(!root->left && !root->right) return n * 10 + root->val;
if(root->left) ret += dfs(root->left, n * 10 + root->val);
if(root->right) ret += dfs(root->right, n * 10 + root->val);
return ret;
}
int sumNumbers(TreeNode* root)
{
return dfs(root, 0);
}
};
leetcode 814.二叉树剪枝
面对这道题目,我们直接抓着根节点就可以了
想象一下,我们先递归一下左,然后拿左链接递归后的结果(因为有可能左边直接变成空了)
右子树同理
接着我们遍历完了左和右,接下来我们就看一下根节点
对于根节点而言,如果左边是空,右边也是空,那就意味着左右都被剪掉了,那么如果这时根节点也是 0 的话,那么直接将根节点变成 nullptr 即可,然后不管怎么样,我们都返回根节点(根节点不一定会变成空)
代码如下:
class Solution {
public:
TreeNode* dfs(TreeNode* root)
{
if(!root) return nullptr;
root->left = dfs(root->left);
root->right = dfs(root->right);
if(!root->left && !root->right && root->val == 0)
root = nullptr;
return root;
}
TreeNode* pruneTree(TreeNode* root)
{
return dfs(root);
}
};
leetcode 98.验证二叉搜索树
想要解决这道题目超级简单,因为二叉搜索树有一个特点就是,中序遍历的时候一定是有序且从小到大的
所以我们就有了一下两种解题思路,第一个是,我们直接创建一个全局的数组,我们再中序遍历二叉树,然后每遍历到一个节点,我们就放一个数到数组里面,最后我们再遍历一下数组,看看是不是升序即可
解法一代码就不写了,很简单可以自己尝试
解法二就是在遍历的时候比较
我们准备俩全局变量,一个表示是否是升序(flag),一个表示要比较的前一个数(pre)
然后我们创建pre的时候,赋值一个INT_MIN给他,那么后面数字一定比他大
最后边遍历边比较,只要不是升序,就改变flag,最后返回flag即可
代码如下:
class Solution {
public:
long pre = LONG_MIN;
bool isValidBST(TreeNode* root)
{
if(!root) return true;
bool l = isValidBST(root->left);
if(root->val > pre)
pre = root->val;
else return false;
bool r = isValidBST(root->right);
return l && r;;
}
};
leetcode 230.二叉搜索树中第K小的元素
这一道题和上一道题目一样,其实也是有两种很容易想出来的做法
首先第一个(比较简单就不写代码了,只讲思路),我们可以直接用一个小根堆,我们遍历一个数就往里面放一个数,遍历完一遍之后,我们直接对这个堆 pop K-1 次即可,最后我们的堆顶就是我们想要的答案
第二种解法就是,我们还是中序遍历,因为这是一个二叉搜索树
我们在全局定义一个变量 time,让这个变量的值和 K 相同,我们每遍历一个元素,我们就将这个time--,当time减小到 0 的时候,我们当前递归到的元素就是我们要的答案,但是我们还要将这个数带出去,所以我们还可以再搞一个全局变量ret,当time为 0 的时候,我们就将那个元素放进ret里面,最后我们再返回这个ret即可
代码如下:
class Solution {
public:
int time;
int ret;
void dfs(TreeNode* root)
{
if(!root) return;
dfs(root->left);
if(!(--time))
{
ret = root->val;
return;
}
dfs(root->right);
}
int kthSmallest(TreeNode* root, int k)
{
time = k;
dfs(root);
return ret;
}
};
leetcode 257.二叉树的所有路径
这个也不难,核心思想就是,先在全局创建一个vector<string>,我们将当前的值和 -> 一个一个传下去,当我们遍历到叶子节点的时候,我们就直接将这个string放进全局vector里面就好了
代码如下:
class Solution {
public:
vector<string> ret;
void dfs(TreeNode* root, string load)
{
if(!root->left && !root->right)
{
ret.push_back(load + to_string(root->val));
return;
}
load = load + to_string(root->val) + "->";
if(root->left) dfs(root->left, load);
if(root->right) dfs(root->right, load);
}
vector<string> binaryTreePaths(TreeNode* root)
{
dfs(root, "");
return ret;
}
};
这篇文章到这里就结束了
接下来我们还会有更多递归系列的博客,如果觉得对你有帮助的可以关注一下!!~( ̄▽ ̄)~*