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

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

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

将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 。

对于双向循环列表,你可以将左右孩子指针作为双向循环链表的前驱和后继指针,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

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

示例 1:
输入:root = [4,2,5,1,3]
在这里插入图片描述
输出:[1,2,3,4,5]

解释:下图显示了转化后的二叉搜索树,实线表示后继关系,虚线表示前驱关系。
在这里插入图片描述

示例 2:
输入:root = [2,1,3]
输出:[1,2,3]

示例 3:
输入:root = []
输出:[]
解释:输入是空树,所以输出也是空链表。

示例 4:
输入:root = [1]
输出:[1]

提示:
-1000 <= Node.val <= 1000
Node.left.val < Node.val < Node.right.val
Node.val 的所有值都是独一无二的
0 <= Number of Nodes <= 2000


思路

二叉搜索树:二叉树,且根节点比所有左子树的值要大,根节点比所有右子树的值要小
左右子树也准从这个准则

在这里插入图片描述

在这里插入图片描述
可以整体把树分为三部分:根节点、左子树、右子树

然后将:
根节点,与左子树最大的节点链接起来
根节点,与右子树最小的节点链接起来

递归

就是一个中序遍历

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val,Node _left,Node _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {

    Node pre;//指针用于保存中序遍历的前一个节点
    Node head;//指针用于记录排序链表的头节点

    public Node treeToDoublyList(Node root) {
        //边界条件
        if(root == null) return null;

        inOrder(root);

        //组成循环链表
        head.left = pre;
        pre.right = head;

        return head;
    }

    //中序遍历
    public void inOrder(Node root){
        //边界条件
        if(root == null) return;

        //中序遍历左子树
        inOrder(root.left);

        if(pre != null){
        	//相对于左子树的最右节点,的右指针,指向root
            pre.right = root;
        }else{
            //找出头结点
            head = root;
        }
        
        //相当于根节点的左指针,指向左子树的最右节点(加上前面那个,形成双向链表)
        root.left = pre;
		
		//当根节点与左子树的关系确定完,则,此时,pre就成了root
        pre = root;
		
		
        System.out.println(root.val);

        //中序遍历右子树
        inOrder(root.right);
    }
}

代码中,只做了 左子树与根节点产生双向链接的操作,而没有做根节点与右子树产生双向链表的操作

这是因为,当中序遍历右子树的时候,执行代码就会将根节点与右子树的最小节点产生链接

如果代码中明确写:根与左子树、根与右子树都产生双向链接,则在中序遍历右子树的时候,就会造成重复

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值