题解 | #二叉搜索树与双向链表#

二叉搜索树与双向链表

http://www.nowcoder.com/practice/947f6eb80d944a84850b0538bf0ec3a5

方法一

已知将二叉搜索树进行中序遍历可以得到由小到大的顺序排列,因此本题最直接的想法就是进行中序遍历。
将中序遍历的结果用数组存储下来,得到的数组是有从小到大顺序的。最后将数组中的结点依次连接即可。
示意图如下:
图片说明
具体代码如下:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    vector<TreeNode*> TreeList;//定义一个数组,根据中序遍历来存储结点。

    void inorder(TreeNode* root){
        if (!root) return;
        inorder(root->left);
        TreeList.push_back(root);
        inorder(root->right);
    }

    TreeNode* Convert(TreeNode* pRootOfTree) {
        if (!pRootOfTree) return pRootOfTree;
        inorder(pRootOfTree);
        for (int i=0;i<TreeList.size()-1;i++){ //根据数组中的顺序将结点连接,注意i的范围。
            TreeList[i]->right = TreeList[i+1];
            TreeList[i+1]->left = TreeList[i];
        }
        return TreeList[0];//数组的头部存储的是双向链表的第一个结点。
    }

};

时间复杂度:O(N),等于中序遍历的时间复杂度。
空间复杂度:O(N),开辟了一个数组来存储结点。

方法二

依旧采取中序遍历。
根据题目的要求1,不能创建新的结点,而方法一的数组中存储的其实是结点,并不满足题意;所以需要在中序遍历的过程中,直接对结点的指针进行调整。
调整的思路如下:
(1)使用一个指针preNode指向当前结点root的前继。(例如root为指向10的时候,preNode指向8,如图所示:)

(2)对于当前结点root,有root->left要指向前继preNode(中序遍历时,对于当前结点root,其左孩子已经遍历完成了,此时root->left可以被修改。);同时,preNode->right要指向当前结点(当前结点是preNode的后继),此时对于preNode结点,它已经完全加入双向链表。
具体代码如下:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    TreeNode* preNode;//preNode一定是全局变量。
    TreeNode* Convert(TreeNode* pRootOfTree) {
        if (!pRootOfTree) return pRootOfTree;
        TreeNode* p = pRootOfTree;
        while (p->left) p = p->left;//找到双向链表的开头。
        inorder(pRootOfTree);
        return p;
    }

    void inorder(TreeNode* root){
        if (!root) return;
        inorder(root->left);
        //当前结点中需要进校的调整。
        root->left = preNode;
        if (preNode){
            preNode->right = root;
        }
        preNode = root;//更新preNode,指向当前结点,作为下一个结点的前继。

        inorder(root->right);
    }
};

时间复杂度:O(N),等于中序遍历的时间复杂度。
空间复杂度:O(N)。没有申请新的空间,但是递归调用栈占用了N的空间。

全部评论
没必要先得到最左节点p,递归过程中发现pre==null,当前节点就是最左节点,记录保存一下,最后返回
3 回复 分享
发布于 2022-03-17 17:57
inorder()少个参数
点赞 回复 分享
发布于 2023-06-01 18:35 江苏
讲的很不清晰 用那种箭头都不知道表达啥 功力待加强
点赞 回复 分享
发布于 2022-08-04 23:09
都不对啊,要求空间复杂度为n(1)
点赞 回复 分享
发布于 2021-12-03 23:05

相关推荐

感谢信收割机Rain:他昨天还和我打瓦,今天咋这样发邮件😅
点赞 评论 收藏
分享
03-18 09:45
莆田学院 golang
牛客749342647号:佬,你这个简历模板是哪个,好好看
点赞 评论 收藏
分享
挣K存W养DOG:我记得好多人说这个公司就是白嫖方案的,现在有大体方案要让你给他展示实现细节了,也是无敌了
点赞 评论 收藏
分享
04-21 13:50
已编辑
北京理工大学 硬件测试
我们学校连夜发了声明,绝了绝了!看完了全部ppt,震碎三观。一般情况下我是站学生的,但这不是一般情况。这男的不能被取消学位吗?自己吃到了红利,靠着面试泄题得到的保研,又反手举报导师。这导师是《被举报系列》里最惨最恋爱脑的了,当然最可怜的是他的同妻……
牛客小黄鱼:看了ppt的聊天记录,真不知道谁才是受害者!有人为你剥过柚子吗?有人为你雪地里等你吗?有人为你写过情书吗?有人为你规划未来吗?有人为你小心翼翼吗?有人为你整页失眠失眠吗? 有人为你送上自己的科研成果吗?有人为你安排出国留学吗?有人愿意给你一个月2万吗?
点赞 评论 收藏
分享
评论
53
5
分享

创作者周榜

更多
牛客网
牛客企业服务