刷題劍指offer

目錄

輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。

方法一:非遞歸版

解題思路:

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.right;
        }
        return root;
    }

 

方法二:遞歸版

解題思路:

1.將左子樹構造成雙鏈表,並返回鏈表頭節點。

2.定位至左子樹雙鏈表最後一個節點。

3.如果左子樹鏈表不爲空的話,將當前root追加到左子樹鏈表。

4.將右子樹構造成雙鏈表,並返回鏈表頭節點。

5.如果右子樹鏈表不爲空的話,將該鏈表追加到root節點之後。

6.根據左子樹鏈表是否爲空確定返回的節點。

public TreeNode Convert(TreeNode root) {
        if(root==null)
            return null;
        if(root.left==null&&root.right==null)
            return root;
        // 1.將左子樹構造成雙鏈表,並返回鏈表頭節點
        TreeNode left = Convert(root.left);
        TreeNode p = left;
        // 2.定位至左子樹雙鏈表最後一個節點
        while(p!=null&&p.right!=null){
            p = p.right;
        }
        // 3.如果左子樹鏈表不爲空的話,將當前root追加到左子樹鏈表
        if(left!=null){
            p.right = root;
            root.left = p;
        }
        // 4.將右子樹構造成雙鏈表,並返回鏈表頭節點
        TreeNode right = Convert(root.right);
        // 5.如果右子樹鏈表不爲空的話,將該鏈表追加到root節點之後
        if(right!=null){
            right.left = root;
            root.right = right;
        }
        return left!=null?left:root;       
    }

方法三:改進遞歸版

解題思路:

思路與方法二中的遞歸版一致,僅對第2點中的定位作了修改,新增一個全局變量記錄左子樹的最後一個節點。

// 記錄子樹鏈表的最後一個節點,終結點只可能爲只含左子樹的非葉節點與葉節點
    protected TreeNode leftLast = null;
    public TreeNode Convert(TreeNode root) {
        if(root==null)
            return null;
        if(root.left==null&&root.right==null){
            leftLast = root;// 最後的一個節點可能爲最右側的葉節點
            return root;
        }
        // 1.將左子樹構造成雙鏈表,並返回鏈表頭節點
        TreeNode left = Convert(root.left);
        // 3.如果左子樹鏈表不爲空的話,將當前root追加到左子樹鏈表
        if(left!=null){
            leftLast.right = root;
            root.left = leftLast;
        }
        leftLast = root;// 當根節點只含左子樹時,則該根節點爲最後一個節點
        // 4.將右子樹構造成雙鏈表,並返回鏈表頭節點
        TreeNode right = Convert(root.right);
        // 5.如果右子樹鏈表不爲空的話,將該鏈表追加到root節點之後
        if(right!=null){
            right.left = root;
            root.right = right;
        }
        return left!=null?left:root;       
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章