【剑指Offer】36. 二叉搜索树与双向链表

题目链接:二叉搜索树与双向链表

题目描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。

题目要求:

1)排序链表,因为是二叉搜索树,构成排序的链表,需要进行中序遍历。

2)不能创建任何新的节点,只能调整节点指针指向,并且是原地转换。即尽量减少时间复杂度。

思路:

1)首先的思路是,对二叉搜索树进行中序遍历成一个排序数组,对数组进行遍历,给每一个节点添加前驱和后继指针。

js代码如下:

var treeToDoublyList = function (root) {
    if (root == null)
        return root;
    let nodes = [];
    midSort(root);
    root = nodes[0];
    const length = nodes.length;
    for (let i = 0; i < length; i++) {
        if (i == 0)
            nodes[i].left = nodes[length - 1];
        else
            nodes[i].left = nodes[i - 1];
        if (i == length - 1)
            nodes[i].right = nodes[0];
        else
            nodes[i].right = nodes[i + 1];
    }
    return root;

    function midSort(root) {
        if (root == null)
            return;
        midSort(root.left);
        nodes.push(root);
        midSort(root.right);
    }
};

2)第二个思路是,在中序遍历的过程中修改前驱和后继指针的指向,非递归方式。

js代码如下:

var treeToDoublyList = function (root) {
    if (root == null)
        return root;
    let nodes = [];
    let cur = root;
    while (cur) {
        nodes.push(cur);
        cur = cur.left;
    }
    head = nodes[nodes.length - 1];
    while (nodes.length !== 0) {
        cur = nodes[nodes.length - 1];
        nodes.pop();
        if (cur.right) {
            let p = cur.right;
            while (p) {
                nodes.push(p);
                p = p.left;
            }
        }
        if (nodes.length >= 1) {
            cur.right = nodes[nodes.length - 1];
            nodes[nodes.length - 1].left = cur;
        }
    }
    head.left=cur;
    cur.right=head;
    return head;
}

3)然后看了一下题解,思路是,在中序遍历过程中修改前驱和后继指针,递归方式。

js代码如下:

var treeToDoublyList = function (root){
    if(root==null)
        return root;
    let head=null;
    let cur=null;
    dfs(root);
    head.left=cur;
    cur.right=head;
    return head;
    //cur按顺序指向当前排好序的节点,
    function dfs(root){
        if(root==null)
            return;
        dfs(root.left);
        if(cur!=null)
            cur.right=root;
        else
            head=root;
        root.left=cur;
        cur=root;
        dfs(root.right);
    }
}

后两个方法中的cur都是指向当前排好序的节点中的最后一个节点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值