27、二叉搜索树与双向链表

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


我的解法

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/

import java.util.ArrayList;

public class Solution {
    //public static ArrayList<TreeNode> list = new ArrayList<>();
    
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null)
            return null;
        
        ArrayList<TreeNode> list = new ArrayList<>();
        inTraverse(pRootOfTree, list);
        
        //把list中树节点连接成双向链表
        TreeNode last = null;
        for(int i = 0; i < list.size() - 1; i ++){
            list.get(i).left = last;
            list.get(i).right = list.get(i + 1);
            last = list.get(i);
        }
        list.get(list.size() - 1).left = last;
        list.get(list.size() - 1).right = null;
        list.get(0).left = null;
        return list.get(0);       
    }
    
    //中序遍历,把树的节点按顺序加入list中
    public void inTraverse(TreeNode pRootOfTree, ArrayList<TreeNode> list){
        if(pRootOfTree == null)
            return;
        if(pRootOfTree.left != null){
            inTraverse(pRootOfTree.left, list);
        }
        list.add(pRootOfTree);
        if(pRootOfTree.right != null){
            inTraverse(pRootOfTree.right, list);
        }
        return;
    }
    
}

算法分析:双链表顺序就是中序顺序。把中序遍历结果按顺序存起来,然后拼接成双链表。 

答案解法

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/

import java.util.ArrayList;

public class Solution {
    
    //开始遍历前,双链表的头部、尾部都为null
    TreeNode head = null;
    TreeNode tail = null;
    
    //把pRootOfTree转换成双链表,得到了链表头部、尾部,但只返回头部
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null)
            return null;
        
        if(pRootOfTree.left != null){
            Convert(pRootOfTree.left);
        }
        
        //中序遍历,那么生成头部、尾部的代码肯定在中间部分
        
        //如果链表为null,则head和tail都是pRootOfTree节点
        if(tail == null){
            head = pRootOfTree;
            tail = pRootOfTree;
        }else{
           //把pRootOfTree加入链表后面,并更新链表尾节点
            tail.right = pRootOfTree;
            pRootOfTree.left = tail;
            tail = pRootOfTree;          
        }
        if(pRootOfTree.right != null){
            Convert(pRootOfTree.right);
        }
        
        return head;       
    }
}
算法分析:利用递归,函数的功能就是把树生成双链表。那么把左树生成双链表(只能返回头部),再拼接上root(需要左树的尾部);再把右树生成双链表,再拼接到root后面即可。求左子树尾部是难点,我一开始不知道怎么求,也是因为没想明白它和双向链表的关系。即左子树的头就是双向链表的头,左子树的尾部就是递归到此时双向链表的尾部。那么最开始都为null,则通过递归,头和尾部的初始值最终就会变成最左边的叶子节点,然后设为全局变量。然后return到上一次循环时,链表尾部就是此最左叶节点。接下来只需要进行拼接工作即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值