剑指offer——二叉搜索树与双向链表(好题)

来源:互联网 发布:中科院下属企业知乎 编辑:程序博客网 时间:2024/06/07 09:45

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

思路:
对于一颗二叉搜索树来说,中序遍历得到的节点顺序,就是排序好的元素。题目要求不能创建新的节点并且变双向链表,所以先用递归中序遍历树得到一个正向的,再倒回来得一个反向的。

很正规的解法,但不够灵活。想不到更好的了。
机试的时候越快解题越好,但面试的时候,复杂度过大的解法可能会让面试官不满意。

import java.util.*;public class Solution {    public ArrayList<TreeNode> list = new ArrayList<>();    public TreeNode Convert(TreeNode pRootOfTree) {        if(pRootOfTree==null)            return null;        helper(pRootOfTree);        int size = list.size();        for(int i = 0; i<size-1; i++){            list.get(i).right = list.get(i+1);            list.get(size-i-1).left = list.get(size-i-2); // 太傻了,直接list.get(i+1).left = list.get(i)就好了        }        return list.get(0);    }    public void helper(TreeNode pRootOfTree){        if(pRootOfTree==null)            return ;        helper(pRootOfTree.left);        list.add(pRootOfTree);        helper(pRootOfTree.right);    }}

题目描述的所谓不能创建新的节点,是指不能创建新的节点对象(堆内存中)。创建引用,指向原有对象,是可以的。

方法一:非递归版解题思路:1.核心是中序遍历的非递归算法。2.修改当前遍历节点与前一遍历节点的指针指向。    import java.util.Stack;    public TreeNode ConvertBSTToBiList(TreeNode root) {        if(root==null)            return null;        Stack<TreeNode> stack = new Stack<TreeNode>();        TreeNode p = root;        TreeNode pre = null;// 用于保存中序遍历序列的上一节点        boolean isFirst = true;        while(p!=null||!stack.isEmpty()){            while(p!=null){                stack.push(p);                p = p.left;            }            p = stack.pop();            if(isFirst){                root = p;// 将中序遍历序列中的第一个节点记为root,其实就是搜索树中值最小的那个点                pre = root;                isFirst = false;            }else{                pre.right = p;                p.left = pre;                pre = p;            }            //执行到这一步之前,已经跳出了寻找左树的循环,并且访问了当前节点,所以这里将p设置为其右子树                   p = p.right;        }        return root;    }
//递归版//直接用中序遍历public class Solution {    TreeNode head = null;    TreeNode realHead = null;    public TreeNode Convert(TreeNode pRootOfTree) {        ConvertSub(pRootOfTree);        return realHead;    }    private void ConvertSub(TreeNode pRootOfTree) {        if(pRootOfTree==null) return;        ConvertSub(pRootOfTree.left);        if (head == null) { //针对中序遍历的头结点,这里要把返回值realHead设置为头结点,同时设置head,防止再次进入此语句            head = pRootOfTree;            realHead = pRootOfTree;        } else {            head.right = pRootOfTree;            pRootOfTree.left = head;            head = pRootOfTree;        }        ConvertSub(pRootOfTree.right);    }}
原创粉丝点击