剑指offer有时候不稳定,会报错失误,空一个小时,或重启电脑,退出浏览器清空缓存。重新编译即可。
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree == nullptr) return nullptr;
TreeNode* pre = nullptr;
convertHelper(pRootOfTree, pre);
TreeNode* res = pRootOfTree;
while(res ->left)
res = res ->left;
return res;
}
void convertHelper(TreeNode* cur, TreeNode*& pre)
{
if(cur == nullptr) return;
convertHelper(cur ->left, pre);
cur ->left = pre;
if(pre) pre ->right = cur;
pre = cur;
convertHelper(cur ->right, pre);
}
};
问题:对于cur ->left 和pre ->right的修改会不会影响之后的遍历?
不会,因为之前已经把上一个节点压栈保存了。
思路分析:用pre这一临时变量记录了中序遍历序列中的前一个visit的接点,然后将pre与currentNode相链接。注意双循环链表最左节点没有left,最右节点没有right。
易错点如下,记录的是中序遍历的前驱节点,而不是中序遍历序列的前驱节点。
public class Solution {
public void convert(TreeNode pre, TreeNode curr){
if(curr == null) {
return ;
}
convert(curr, curr.left);
pre.right = curr;
curr.left = pre;
convert(curr, curr.right);
}
public TreeNode Convert(TreeNode pRootOfTree) {
convert(pRootOfTree,pRootOfTree);
TreeNode res = pRootOfTree;
while(res != null) res = res.left;
return res;
}
}
错误方法,该方法只能输出部分序列,原因是递归调用参数有问题,不能把pre放进参数里面,否则回溯时会回溯以前的pre,因为引用在变化,而不是中序遍历的上一个节点。
也就是说如果对参数列表中的引用做了修改,那么它还是不适合放入参数列表中。
public class Solution {
public void convert(TreeNode pre, TreeNode curr){
if(curr == null){
return ;
}
pre = null;
convert(pre, curr.left);
if(pre != null) pre.right = curr;
curr.left = pre;
pre = curr;
convert(pre, curr.right);
}
public TreeNode Convert(TreeNode pRootOfTree) {
convert(null , pRootOfTree);
TreeNode res = pRootOfTree;
while(res.left != null) res = res.left;
return res;
}
}
正确解法:
//用一个局部变量记录二叉树中序遍历的上一个访问的节点,并设置其right域。
public class Solution {
public TreeNode pre = null;
public void convert(TreeNode curr){
if(curr == null) return ;
convert(curr.left);
if(pre != null) pre.right = curr;
curr.left = pre;
pre = curr;
convert(curr.right);
}
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null) return null;
convert(pRootOfTree);
while(pRootOfTree.left != null) pRootOfTree = pRootOfTree.left;
return pRootOfTree;
}
}
什么时候要将变量放在递归的参数列表中,“希望递归遍历时变量能还原到当初访问的时候的值”的情况下才将变量放进参数。
以后搜算法题csdn搜,百度搜不到隐藏的好答案