(Java)leetcode-449 Serialize and Deserialize BST (序列化和反序列化二叉搜索樹)

題目描述

序列化是將數據結構或對象轉換爲一系列位的過程,以便它可以存儲在文件或內存緩衝區中,或通過網絡連接鏈路傳輸,以便稍後在同一個或另一個計算機環境中重建。

設計一個算法來序列化和反序列化二叉搜索樹。 對序列化/反序列化算法的工作方式沒有限制。 您只需確保二叉搜索樹可以序列化爲字符串,並且可以將該字符串反序列化爲最初的二叉搜索樹。

編碼的字符串應儘可能緊湊。

注意:不要使用類成員/全局/靜態變量來存儲狀態。 你的序列化和反序列化算法應該是無狀態的。

思路

參考leetcode-297 Serialize and Deserialize Binary Tree (二叉樹的序列化與反序列化)
該題的解法是對於所有二叉樹一般化的解法,可以直接套用在本題,因爲二叉搜索樹是一種特殊的二叉樹。

那麼如何利用二叉搜索樹的性質,對一般化的解法進行優化呢?

在一般化的解法中,序列化時,當遇到空節點時,我們必須在字符串中添加"null"或其他字符,來標記這個位置應該是空節點,以便在反序列化時構造正確的樹。

而對於二叉搜索樹,可以不需要"null"來標記空節點,那麼在構造樹時,利用其性質——左孩子的值小於父節點,右孩子的值大於父節點——來判斷某個位置是否應該爲空。

反序列化時,將字符串轉爲隊列,按照先序構造樹,每次訪問到一個位置,傳入一對上下界,用於判斷隊列首位的值是否在這個範圍內——

  • 若在範圍內,說明這個值應該處於樹的這個位置,那麼出隊,並遞歸構造左右子樹。構造左子樹時,將此節點值作爲上界(左孩子的值必須小於此節點);同理,構造右子樹時,將此節點值作爲下界。
  • 若不在範圍內,說明隊首的值不應該在此位置,結束遞歸。

代碼

public class Codec {

    // 將BST序列化爲字符串
    public String serialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        serialize(root, sb);
        return sb.toString();
    }
    
    // 前序遍歷,遇到空節點不添加null
    public void serialize(TreeNode root, StringBuilder sb) {
        if (root == null) return;
        sb.append(root.val).append(",");
        serialize(root.left, sb);
        serialize(root.right, sb);
    }

    // 將字符串反序列化爲BST
    public TreeNode deserialize(String data) {
        if (data.isEmpty()) return null;
        // 將字符串轉爲隊列
        Queue<String> q = new LinkedList<>(Arrays.asList(data.split(",")));
        return deserialize(q, Integer.MIN_VALUE, Integer.MAX_VALUE);
    }
    
    public TreeNode deserialize(Queue<String> q, int lower, int upper) {
        // 隊列爲空,說明樹已經構造完畢,遞歸結束
        if (q.isEmpty()) return null;
        
        // 取隊首元素的值
        String s = q.peek();
        int val = Integer.parseInt(s);

        // 如果值不在範圍中,說明這個位置應該爲空,結束本層遞歸
        if (val < lower || val > upper) return null;
        
        // 如果值在範圍中,將其出隊,用值構造樹
        q.poll();
        TreeNode root = new TreeNode(val);

        // 將root值作爲上界,構造左子樹
        root.left = deserialize(q, lower, val);
        // 將root值作爲下界,構造右子樹
        root.right = deserialize(q, val, upper);
        
        return root;
    }
}

執行用時:6 ms, 在所有 Java 提交中擊敗了93.02%的用戶
內存消耗:40.9 MB, 在所有 Java 提交中擊敗了100.00%的用戶

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