[LintCode] Serialize and Deserialize Binary Tree(二叉樹的序列化和反序列化)

描述

設計一個算法,並編寫代碼來序列化和反序列化二叉樹。將樹寫入一個文件被稱爲“序列化”,讀取文件後重建同樣的二叉樹被稱爲“反序列化”。

如何反序列化或序列化二叉樹是沒有限制的,你只需要確保可以將二叉樹序列化爲一個字符串,並且可以將字符串反序列化爲原來的樹結構。

對二進制樹進行反序列化或序列化的方式沒有限制,LintCode將您的serialize輸出作爲deserialize的輸入,它不會檢查序列化的結果。

樣例

給出一個測試數據樣例, 二叉樹{3,9,20,#,#,15,7},表示如下的樹結構:

  3
 / \
9  20
  /  \
 15   7

我們的數據是進行 BFS 遍歷得到的。當你測試結果 wrong answer時,你可以作爲輸入調試你的代碼。

你可以採用其他的方法進行序列化和反序列化。

代碼

GitHub 的源代碼,請訪問下面的鏈接:

https://github.com/cwiki-us/java-tutorial/blob/master/src/test/java/com/ossez/lang/tutorial/tests/lintcode/LintCode0007SerializeAndDeserialize.java



package com.ossez.lang.tutorial.tests.lintcode;

import java.util.ArrayList;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ossez.lang.tutorial.models.TreeNode;

/**
 * <p>
 * 7
 * <ul>
 * <li>@see <a href=
 * "https://www.cwiki.us/display/ITCLASSIFICATION/Serialize+and+Deserialize+Binary+Tree">https://www.cwiki.us/display/ITCLASSIFICATION/Serialize+and+Deserialize+Binary+Tree</a>
 * <li>@see<a href=
 * "https://www.lintcode.com/problem/serialize-and-deserialize-binary-tree">https://www.lintcode.com/problem/serialize-and-deserialize-binary-tree</a>
 * </ul>
 * </p>
 * 
 * @author YuCheng
 *
 */
public class LintCode0007SerializeAndDeserialize {

	private final static Logger logger = LoggerFactory.getLogger(LintCode0007SerializeAndDeserialize.class);

	/**
	 * 
	 */
	@Test
	public void testMain() {
		logger.debug("BEGIN");
		String data = "{3,9,20,#,#,15,7}";

		System.out.println(serialize(deserialize(data)));

	}

	/**
	 * Deserialize from array to tree
	 * 
	 * @param data
	 * @return
	 */
	private TreeNode deserialize(String data) {
		// NULL CHECK
		if (data.equals("{}")) {
			return null;
		}

		ArrayList<TreeNode> treeList = new ArrayList<TreeNode>();

		data = data.replace("{", "");
		data = data.replace("}", "");
		String[] vals = data.split(",");

		// INSERT ROOT
		TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
		treeList.add(root);

		int index = 0;
		boolean isLeftChild = true;
		for (int i = 1; i < vals.length; i++) {
			if (!vals[i].equals("#")) {
				TreeNode node = new TreeNode(Integer.parseInt(vals[i]));
				if (isLeftChild) {
					treeList.get(index).left = node;
				} else {
					treeList.get(index).right = node;
				}
				treeList.add(node);
			}

			// LEVEL
			if (!isLeftChild) {
				index++;
			}

			// MOVE TO RIGHT OR NEXT LEVEL
			isLeftChild = !isLeftChild;
		}

		return root;

	}

	/**
	 * 
	 * @param root
	 * @return
	 */
	public String serialize(TreeNode root) {
		// write your code here
		if (root == null) {
			return "{}";
		}

		ArrayList<TreeNode> queue = new ArrayList<TreeNode>();
		queue.add(root);

		for (int i = 0; i < queue.size(); i++) {
			TreeNode node = queue.get(i);
			if (node == null) {
				continue;
			}
			queue.add(node.left);
			queue.add(node.right);
		}

		while (queue.get(queue.size() - 1) == null) {
			queue.remove(queue.size() - 1);
		}

		StringBuilder sb = new StringBuilder();
		sb.append("{");
		sb.append(queue.get(0).val);
		for (int i = 1; i < queue.size(); i++) {
			if (queue.get(i) == null) {
				sb.append(",#");
			} else {
				sb.append(",");
				sb.append(queue.get(i).val);
			}
		}
		sb.append("}");
		return sb.toString();
	}

}


點評

本題目主要需要你對二叉樹的遍歷方法有所瞭解。

遍歷二叉樹主要有 2 類方法,分別爲深度優先(DFS)和廣度優先(BFS)。

在深度優先中,你有又可以使用前序,中序和後序搜索方法,你可以使用遞歸或者非遞歸算法實現。對於廣度優先算法,一般都會採用非遞歸的實現方法進行實現。

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