这种肯定是通过试探,如果是指定节点,那就直接返回,如果不是,就返回上一层继续遍历,因此是一个递归+回溯的问题,代码如下:
string res="";
string get_road(TreeNode* root) {
dfs(root,5,"");//假设寻找的节点值为5
return res;
}
void dfs(TreeNode* root,const int& target,const string& s)//尽量用临时变量存储,临时变量要用常引用
{
if(root==NULL) return;
else if(root->val==target)
res=s+char(root->val+'0);
else{
//这里也不要写成s+=char(root->val+'0'),然后作为参数
//因为这样s就变化了,如果这里是for循环那么s就回溯不了了,就要先pop_back(),不方便
//1.for循环如电话号码组合问题,参考LeetCode17-电话号码的字母组合:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/以及LeetCode-八皇后
//2.如果必须改变当前值,事后就得变回来,如LeetCode46-全排列问题:https://leetcode-cn.com/problems/permutations/
dfs(root->left,target,s+char(root->val+'0'));//这样在下一句dfs的时候,s是没变化的,也就是回溯到了前一个状态
dfs(root->right,target,s+char(root->val+'0'));//s+char(...)相当于一个临时变量,如果函数参数s不是常引用,这里会出错(可以不用引用)
}
}
下列讨论纯属个人见解
主要是针对dfs函数最后一个参数的问题,假设最后一个变量用全局变量res:
1.首先明确返回类型,如果是将res返回,也就是返回类型为vector<>,那当最后 root==NULL 时应该返回什么呢,返回发当前的res肯定是错的,因为当路径是错的时,返回的res肯定也是错的,所以返回类型只能是void。
2.如上,如果返回类型是void,那么只能内部修改res,即最后一个参数为string& res(不能是const,因为const类型的res不允许修改,上面可以是因为传递的是一个临时变量,不需要修改s,直接s+c临时变量就可以作为参数,而当参数类型是string& res时,参数不能是临时变量res+c).
3.确定第三个参数类型为string& res后,在进行递归时就修改了res,在进行回溯时,需要pop_back(),不好修改。
综上,尽量用临时变量s保存路径(作为固定格式),再把s转化为想要的结果。
2020.09.28更新
如果所给的树是二叉搜索树(排序树),那么大可不必去回溯试探,直接通过二叉搜索树的特点(小的在左子树,大的在右子树),直到找到节点。下面是LeetCode的一道题:剑指 Offer 34. 二叉树中和为某一值的路径