Leetcode 572 另一個樹的子樹
阿新 • • 發佈:2020-12-08
Leetcode 572 另一個樹的子樹
資料結構定義:
給定兩個非空二叉樹 s 和 t,檢驗s 中是否包含和 t 具有相同結構和節點值的子樹。s 的一個子樹包括 s 的一個節點和這個節點的所有子孫。s 也可以看做它自身的一棵子樹。 示例 1: 給定的樹 s: 3 / \ 4 5 / \ 1 2 給定的樹 t: 4 / \ 1 2 返回 true,因為 t 與 s 的一個子樹擁有相同的結構和節點值。 示例 2: 給定的樹 s: 3 / \ 4 5 / \ 1 2 / 0 給定的樹 t: 4 / \ 1 2 返回 false。 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */
遞迴方式:
class Solution { public boolean isSubtree(TreeNode s, TreeNode t) { return dfs(s,t); } private boolean dfs(TreeNode s,TreeNode t){ if(s == null){ return false; } return check(s,t) || dfs(s.left,t) || dfs(s.right,t); } private boolean check(TreeNode s,TreeNode t){ if(s == null && t == null){ return true; } if(s == null || t == null || s.val != t.val){ return false; } return check(s.left,t.left) && check(s.right,t.right); } }
KMP方式:
/* * 思路: 一棵子樹上的點在 先序遍歷 中是連續的,所以先得到兩個樹的先序遍歷結果 * 對於葉子節點為空的情況,通過填充lNull 和 rNull 做處理 * 最後使用 kmp 遍歷,查詢是否匹配 */ class Solution { List<Integer> sList = new ArrayList<>(); List<Integer> tList = new ArrayList<>(); int lNull = Integer.MAX_VALUE - 1, rNull = Integer.MAX_VALUE - 2; public boolean isSubtree(TreeNode s, TreeNode t) { getDFSOrder(s, sList); getDFSOrder(t, tList); return kmp(); // return bf(); } private void getDFSOrder(TreeNode node,List<Integer> list){ if(node == null) return; list.add(node.val); if(node.left == null) list.add(lNull); else getDFSOrder(node.left,list); if(node.right == null) list.add(rNull); else getDFSOrder(node.right,list); } private boolean kmp(){ if(sList.size() == 0 || tList.size() == 0){ return false; } int sLen = sList.size(),tLen = tList.size(); int[] next = new int[tLen]; Arrays.fill(next, -1); for (int i = 1,j = -1; i < tLen; i++) { while(j != -1 && !(tList.get(i).equals(tList.get(j + 1)))) j = next[j]; if(tList.get(i).equals(tList.get(j + 1))) j++; next[i] = j; } for (int i = 0,j = -1; i < sLen; i++) { while(j != -1 && !(sList.get(i).equals(tList.get(j + 1)))) j = next[j]; if(sList.get(i).equals(tList.get(j + 1))) j++; if(j == tLen - 1) return true; } return false; } //暴力匹配方式 private boolean bf(){ if(sList.size() == 0 || tList.size() == 0){ return false; } int i = 0,j = 0; while(i < sList.size() && j < tList.size()){ if(sList.get(i).equals(tList.get(j))){ i++; j++; }else{ i = i - j + 1; j = 0; } } return j == tList.size(); } }
樹雜湊方式:
//待續