给定两个二叉树,编写一个函数来检验它们是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
输入: 1 1
/ \ /
2 3 2 3
[1,2,3], [1,2,3]
输出: true
示例 2:
输入: 1 1
/
2 2
[1,2], [1,null,2]
输出: false
示例 3:
输入: 1 1
/ \ /
2 1 1 2
[1,2,1], [1,1,2]
输出: false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/same-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/**
- 这道题本身解题思路非常简单,但是这道题真正的价值是树的构建。如何自己构建一棵树?这道题就给出了标准
- 首先使用封装一棵树,树有三要素,结点,左子树,右子树
- 然后定义构造方法,形成一颗树。这道题的价值就是在这里,下次需要树结构的时候,直接照搬即可。
*/
public class 相同的树 {
public static 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;
}
}
/**
* 首先题目是判断两颗二叉树是否相等。那就需要遍历二叉树,课程教过遍历二叉树有三种方法
* 中序遍历:左根右
* 前序遍历:根左右
* 后序遍历:左右根
*/
```java
public static boolean isSameTree(TreeNode p,TreeNode q) {
if (p == null && q == null) {return true;}
if (p == null || q == null) { return false;}
/**
* 首先来个前序遍历,分别对两个数的结点进行存储
*/
List<String> pList=new ArrayList<>();
List<String> qList=new ArrayList<>();
前序遍历(p,pList);
前序遍历(q,qList);
//
// 中序遍历(p, pList);
// 中序遍历(q, qList);
//
// 后序遍历(p, pList);
// 后序遍历(q, qList);
if (pList.size()!=qList.size()){return false;}
for (int i = 0; i <qList.size(); i++) {
if (!pList.get(i).equals(qList.get(i))){
return false;
}
}
return true;
}
```java
public static void 前序遍历(TreeNode root,List list) {
if (root != null) {
list.add(String.valueOf(root.val));
前序遍历(root.left,list);
前序遍历(root.right,list);
}
if (root==null){
list.add(" ");
}
}
public static void 中序遍历(TreeNode root,List list) {
if (root != null) {
中序遍历(root.left,list);
list.add(String.valueOf(root.val));
中序遍历(root.right,list);
}
if (root==null){
list.add(" ");
}
}
public static void 后序遍历(TreeNode root,List list) {
if (root != null) {
后序遍历(root.left,list);
后序遍历(root.right,list);
list.add(String.valueOf(root.val));
}
if (root==null){
list.add(" ");
}
}
贴上一个前序排序的通过图,时间复杂度还是可以的。不能忘本,最基础的东西还是最实用的,后面遇到较难的算法,从底层开始思考,解法就敞开了。
/**
* 上述都是遍历树的基本方法
* 现在来一点难度的搜索方法
* DFS:
* 深度优先搜索(DFS) 深度优先搜索在搜索过程中访问某个顶点后,需要递归地访问此顶点的所有未访问过的相邻顶点。就像我们遇到喜欢的女孩子,一直追求她,追到撞南墙了,无路可走了,就回溯,找回自己,另寻他路。比起失望,我最怕遗憾,所以每件事都要以dfs的效率去执行,时间复杂度虽然高,但是不遗憾。代码思想都是从生活经验来的,多体验生活。
* 1.初始状态,从根节点开始
* 2然后一直往左节点开始搜索,搜到没有了,回溯,然后一直往右搜索,搜到叶子结点为止
*/
public boolean DFS(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
}
if (p == null || q == null) {
return false;
}
if (p.val != q.val) {
return false;
}
return DFS(p.left, q.left) && DFS(p.right, q.right);
}
/**
*相比对dfs,bfs比较好理解。
* 广度优先搜索在进一步遍历图中顶点之前,先访问当前顶点的所有邻接结点。
*/
public boolean BFS(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
} else if (p == null || q == null) {
return false;
}
Queue<TreeNode> queue1 = new LinkedList<TreeNode>();
Queue<TreeNode> queue2 = new LinkedList<TreeNode>();
//存入根树
queue1.offer(p);
queue2.offer(q);
while (!queue1.isEmpty() && !queue2.isEmpty()) {
//弹出树
TreeNode node1 = queue1.poll();
TreeNode node2 = queue2.poll();
if (node1.val != node2.val) {
return false;
}
//然后比较第二层的结点值
TreeNode left1 = node1.left, right1 = node1.right, left2 = node2.left, right2 = node2.right;
if (left1 == null ^ left2 == null) {
//^运算符跟 | 类似,但有一点不同的是 如果两个操作位都为1的话,结果产生0
return false;
}
if (right1 == null ^ right2 == null) {
return false;
}
if (left1 != null) {
//存入取出根节点后的树,相当于遍历完一层,到下一层了
queue1.offer(left1);
}
if (right1 != null) {
queue1.offer(right1);
}
if (left2 != null) {
queue2.offer(left2);
}
if (right2 != null) {
queue2.offer(right2);
}
}
return queue1.isEmpty() && queue2.isEmpty();
}
public static void main(String[] args) {
TreeNode RtreeNode1=new TreeNode(1,null,null);
TreeNode RtreeNode2=new TreeNode(1,null,null);
TreeNode LtreeNode1=new TreeNode(2,null,null);
TreeNode LtreeNode2=new TreeNode(2,null,null);
/**
* [1,2]
* [1,null,2]
*/
TreeNode qtreeNode=new TreeNode(1,LtreeNode1,null);
TreeNode ptreeNode=new TreeNode(1,null,RtreeNode2);
boolean sameTree = isSameTree(ptreeNode, qtreeNode);
System.out.println(sameTree);
}
孤芳自赏,每做一次,我们都是模糊的、虚幻的、不确定的
}