题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
解题思路
一开始苦思冥想,无果。然后看书上的一图得到启发,如下。
即先保存根的左右子树,对于根结点的左子树,如果左子树的右子树不等于根结点(即没有修改过),查找左子树里最右端的结点,将这个结点的右子树修改为根结点,根结点的左子树修改为这个结点;对于根结点的右子树,如果右子树的左子树不等于根结点(即没有修改过),查找右子树最左端的结点,将这个结点的左子树修改为根结点,再将根结点的右子树修改为这个结点。递归之前保存的根结点的左右子树。特别要注意加粗的文字,避免程序陷入死循环的办法。
Code
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* FindRightestNode(TreeNode* pRoot) {
if(!pRoot) return nullptr;
TreeNode* rightestNode = pRoot;
if(pRoot->right) {
return FindRightestNode(pRoot->right);
}
return pRoot;
}
TreeNode* FindLeftestNode(TreeNode* pRoot) {
if(!pRoot) return nullptr;
TreeNode* leftestNode = pRoot;
if(pRoot->left) {
return FindLeftestNode(pRoot->left);
}
return pRoot;
}
void ConvertCore(TreeNode* pRoot) {
if(!pRoot) return ;
if(pRoot->left) {
if(pRoot->right) {
if(pRoot->left->right == pRoot && pRoot->right->left == pRoot) return ;
} else {
if(pRoot->left->right == pRoot) return ;
}
} else {
if(pRoot->right) {
if(pRoot->right->left == pRoot) return ;
}
}
TreeNode *pLeftestNode = nullptr, *pRightestNode = nullptr;
TreeNode *pLeft = pRoot->left, *pRight = pRoot->right;
if(pRoot->left && pRoot->left->right != pRoot) {
//如果左子树的右子树是当前结点的话则不用换,否则程序会陷入死循环
pRightestNode = FindRightestNode(pRoot->left);
pRightestNode->right = pRoot;
pRoot->left = pRightestNode;
}
if(pRoot->right && pRoot->right->left != pRoot) {
//如果左子树的右子树是当前结点的话则不用换,否则程序会陷入死循环
pLeftestNode = FindLeftestNode(pRoot->right);
pRoot->right = pLeftestNode;
pLeftestNode->left = pRoot;
}
if(pLeft) {
ConvertCore(pLeft);
}
if(pRight) {
ConvertCore(pRight);
}
}
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(!pRootOfTree) {
return nullptr;
}
ConvertCore(pRootOfTree);
return FindLeftestNode(pRootOfTree);
}
};
- java1
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public void ConvertCore(TreeNode pRootOfTree) {
if(pRootOfTree == null || (pRootOfTree.left == null && pRootOfTree.right == null)) return ;
else if(pRootOfTree.right != null && pRootOfTree.right.left == pRootOfTree) {
if(pRootOfTree.left == null || (pRootOfTree.left.right == pRootOfTree)) return;
} else if(pRootOfTree.left != null && pRootOfTree.left.right == pRootOfTree) {
if(pRootOfTree.right == null) return;
}
TreeNode left = pRootOfTree.left, right = pRootOfTree.right;
TreeNode pre = left, post = right;
if(left != null && left.right != pRootOfTree) {
while(pre.right != null) {
pre = pre.right;
}
pre.right = pRootOfTree;
pRootOfTree.left = pre;
}
if(right != null && right.left != pRootOfTree) {
while(post.left != null) {
post = post.left;
}
post.left = pRootOfTree;
pRootOfTree.right = post;
}
ConvertCore(left);
ConvertCore(right);
}
public TreeNode Convert(TreeNode pRootOfTree) {
ConvertCore(pRootOfTree);
TreeNode root = pRootOfTree;
while(root != null && root.left != null) {
root = root.left;
}
return root;
}
}
- java
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null || (pRootOfTree.left == null && pRootOfTree.right == null)) return pRootOfTree;
TreeNode left = Convert(pRootOfTree.left);
TreeNode pre = left;
while(pre != null && pre.right != null) {
pre = pre.right;
}
if(pre != null) {
pre.right = pRootOfTree;
pRootOfTree.left = pre;
}
TreeNode post = Convert(pRootOfTree.right);
if(post != null) {
post.left = pRootOfTree;
pRootOfTree.right = post;
}
return left == null ? pRootOfTree : left;
}
}
- 评论区的代码
//链接:https://www.nowcoder.com/questionTerminal/947f6eb80d944a84850b0538bf0ec3a5
//来源:牛客网
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);
}
};
总结
- java中的引用是地址,它指向了对象,有点像c++的指针
- 直接用中序遍历更不容易出错