左神算法:判断 t1 树中是否有与 t2 树拓扑结构完全相同的子树(Java版)
本題來自左神《程序員代碼面試指南》“判斷 t1 樹中是否有與 t2 樹拓撲結構完全相同的子樹”題目。
題目
給定彼此獨立的兩棵樹頭節點分別為 t1 和 t2,判斷 t1 中是否有與 t2 樹拓撲結構完全相同
的子樹。
例如,如圖3-36 所示的 t1 樹和如圖 3-37 所示的 t2 樹。
題解
如果 t1 的節點數為 N,t2 的節點數為 M,則本題最優解是時間復雜度為O(N+M)的方法。
首先簡單介紹一個時間復雜度為O(N×M)的方法:
對于 t1 的每棵子樹,都去判斷是否與 t2 樹的拓撲結構完全一樣,這個過程的時間復雜度為O(M),t1 的子樹一共有 N 棵,所以時間復雜度為O(N×M),這種方法在本文中不再詳述。
下面重點介紹一下時間復雜度為O(N+M)的方法:
首先把 t1 樹和 t2 樹按照先序遍歷的方式序列化,關于這個內容,請閱讀“二叉樹的序列化和反序列化”問題。以題目的例子來說,t1 樹序列化后的結果為“1!2!4!#!8!#!#!5!9!#!#!#!3!6!#!#!7!#!#!”,記為t1Str。t2 樹序列化后的結果為“2!4!#!8!#!#!5!9!#!#!#!”,記為 t2Str。
接下來,只要驗證 t2Str 是否是 t1Str 的子串即可,這個用 KMP 算法可以在線性時間內解決。
因此,t1 序列化的過程為 O(N),t2 序列化的過程為 O(M),KMP 解決 t1Str 和 t2Str 的匹配問題 O(M+N),所以時間復雜度為 O(M+N)。
有關 KMP 算法的內容,請讀者閱讀“KMP 算法”問題,關于這個算法非常清晰的解釋,這里不再詳述。
代碼
含測試用例
package chapter_3_binarytreeproblem;public class Problem_12_T1SubtreeEqualsT2 {public static class Node {public int value;public Node left;public Node right;public Node(int data) {this.value = data;}}public static boolean isSubtree(Node t1, Node t2) {String t1Str = serialByPre(t1);String t2Str = serialByPre(t2);return getIndexOf(t1Str, t2Str) != -1;}public static String serialByPre(Node head) {if (head == null) {return "#!";}String res = head.value + "!";res += serialByPre(head.left);res += serialByPre(head.right);return res;}// KMPpublic static int getIndexOf(String s, String m) {if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {return -1;}char[] ss = s.toCharArray();char[] ms = m.toCharArray();int[] nextArr = getNextArray(ms);int index = 0;int mi = 0;while (index < ss.length && mi < ms.length) {if (ss[index] == ms[mi]) {index++;mi++;} else if (nextArr[mi] == -1) {index++;} else {mi = nextArr[mi];}}return mi == ms.length ? index - mi : -1;}public static int[] getNextArray(char[] ms) {if (ms.length == 1) {return new int[]{-1};}int[] nextArr = new int[ms.length];nextArr[0] = -1;nextArr[1] = 0;int pos = 2;int cn = 0;while (pos < nextArr.length) {if (ms[pos - 1] == ms[cn]) {nextArr[pos++] = ++cn;} else if (cn > 0) {cn = nextArr[cn];} else {nextArr[pos++] = 0;}}return nextArr;}public static void main(String[] args) {Node t1 = new Node(1);t1.left = new Node(2);t1.right = new Node(3);t1.left.left = new Node(4);t1.left.right = new Node(5);t1.right.left = new Node(6);t1.right.right = new Node(7);t1.left.left.right = new Node(8);t1.left.right.left = new Node(9);Node t2 = new Node(2);t2.left = new Node(4);t2.left.right = new Node(8);t2.right = new Node(5);t2.right.left = new Node(9);System.out.println(isSubtree(t1, t2));}} 超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的左神算法:判断 t1 树中是否有与 t2 树拓扑结构完全相同的子树(Java版)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 268. 丢失的数字(
- 下一篇: 本地 MarkDown 怎么部署到服务器