数据结构定义:
给定两个非空二叉树 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();
}
}
树哈希方式:
//待续