1. 程式人生 > 其它 >LeetCode:297. 二叉樹的序列化與反序列化(困難)(劍指 Offer 37)

LeetCode:297. 二叉樹的序列化與反序列化(困難)(劍指 Offer 37)

技術標籤:91天學演算法二叉樹演算法佇列c++資料結構

題目描述

序列化是將一個數據結構或者物件轉換為連續的位元位的操作,進而可以將轉換後的資料儲存在一個檔案或者記憶體中,同時也可以通過網路傳輸到另一個計算機環境,採取相反方式重構得到原資料。

請設計一個演算法來實現二叉樹的序列化與反序列化。這裡不限定你的序列 / 反序列化演算法執行邏輯,你只需要保證一個二叉樹可以被序列化為一個字串並且將這個字串反序列化為原始的樹結構。
示例說明: 不要使用類的成員 / 全域性 / 靜態變數來儲存狀態,你的序列化和反序列化演算法應該是無狀態的。

題解

題意: 把二叉樹轉化為一個字串,並且還能把這個字串還原成原來的二叉樹。

採用寬度優先搜尋BFS, 一層一層從往下遍歷, 當遇到某節點左右節點為空時, 可以用特殊字元做好標記, 以便反序列化時由陣列恢復成樹。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:
    // Encodes a tree to a single string.
//佇列層序遍歷。 string serialize(TreeNode* root) { string res = ""; if(root==NULL) return ""; queue<TreeNode*> my_queue; my_queue.push(root); TreeNode * cur = new TreeNode(0); while(!my_queue.empty()) { //記錄佇列裡的元素長度
int len = my_queue.size(); while(len--) { cur = my_queue.front(); my_queue.pop(); if(cur==NULL) { //res = res + "$"; res.push_back('$'); }else { //res = res + to_string(cur->val); res.append(to_string(cur->val)); } res.push_back(','); if(cur!=NULL) { my_queue.push(cur->left); my_queue.push(cur->right); } } } res.pop_back(); return res; } // Decodes your encoded data to tree. //重建二叉樹。先將節點存起來,然後再遍歷給他們建立結構! TreeNode* deserialize(string data) { //處理特殊 if(data.size()==0) return NULL; int len = data.size(); int i = 0; vector<TreeNode*> vec; while(i<len) { //遇到逗號停下來。 string str = ""; cout << "data[" << i << "]=" << data[i] << endl; cout << "i=" << i << endl; while(i<len&&data[i]!=',') { str.push_back(data[i]); cout << "str=" << str << endl; i++; } //新建根節點. if(str=="$") { TreeNode * temp = NULL; vec.push_back(temp); //直接存NULL也可以。 }else{ int temp = std::stoi(str);//把數字字串轉換成int輸出, 標頭檔案是#include<cstring> TreeNode * cur = new TreeNode(temp); vec.push_back(cur); } i++; } //遍歷vec,構建二叉樹的結構。 int j = 1; for(int i=0;j<vec.size();i++) { if(vec[i]==NULL) continue; if(j<vec.size()) vec[i]->left = vec[j++]; if(j<vec.size()) vec[i]->right = vec[j++]; } return vec[0]; } }; // Your Codec object will be instantiated and called as such: // Codec codec; // codec.deserialize(codec.serialize(root));

複雜度分析

  • 時間複雜度:O(N),其中 N 為樹的節點數。
  • 空間複雜度:O(Q),其中 Q 為佇列長度,最壞的情況是滿二叉樹,此時和 N 同階,其中 N 為樹的節點總數。

參考

面試題37. 序列化二叉樹(層序遍歷 BFS ,清晰圖解)python3)
渣渣發現的問題。希望更多人看到!c++
位元組題庫 - #劍37 - 困難 - 序列化二叉樹 - 2刷
BFS和DFS兩種方式解決
(297. 二叉樹的序列化與反序列化)