劍值offer 36 二叉搜索樹與雙向鏈表(java)

面試題36 二叉搜索樹與雙向鏈表

題目描述

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

題解

題目要求排序的雙向鏈表,則:

  1. 採用中序遍歷,剛好節點的值爲一個遞增的序列。
  2. 雙向鏈表: 則鏈表中相鄰的兩個節點之間(如果驅節點 pre ,當前節點 cur)有則 pre.right = cur, cur.left = pre

算法流程

採用非遞歸的中序dfs,用一個棧記錄訪問次序,一個輔助鏈表記錄訪問結果,在輔助鏈表中修改指針指向。返回輔助鏈表的第一個節點;

複雜度分析:
時間複雜度 O(N) : N 爲二叉樹的節點數,中序遍歷需要訪問所有節點。
空間複雜度 O(N) : 輔助鏈表res使用 O(N)空間。輔助棧stack最差情況下也是O(N)空間。

import java.util.ArrayList;
import java.util.Stack;

public class Solution {
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null) return null;
        if(pRootOfTree.left == null && pRootOfTree.right == null) return pRootOfTree;
        ArrayList<TreeNode> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode temp = pRootOfTree;
        
        // 形成一箇中序遍歷的結果,並添加指針。
        while(!stack.empty() || temp != null){
            if(temp != null){
                stack.add(temp);
                temp = temp.left;
            }else{
                temp = stack.pop();
                res.add(temp);
                temp = temp.right;
            }
        }
        // 修改鏈表指針指向。
        for(int i = 0; i < res.size()-1; i++){
            res.get(i+1).left = res.get(i);
            res.get(i).right = res.get(i+1);
        }
        return res.get(0);
    }
}

遞歸寫法:
時間複雜度 O(N) : N 爲二叉樹的節點數,中序遍歷需要訪問所有節點。
空間複雜度 O(N) : 當二叉樹退化爲鏈表時,遞歸輔助棧最差情況下也是O(N)空間。

public class Solution {
    TreeNode head = null; 
    TreeNode  pre = null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        dfs(pRootOfTree);
        return head;
    }
    void dfs(TreeNode cur){
        if(cur == null) return ;
        dfs(cur.left);
        if(pre != null) pre.right = cur;  // 一般情況
        else head = cur;
        cur.left = pre;
        pre = cur;
        dfs(cur.right);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章