2019年9月15日
继续弥补《数据结构与算法》的不足,今天抽中了“树”。决定先把基础题做一遍,打好基础。
目录
题目:
解决方法1:
解决思路:
性能结果:
解决方法2:
思路:深度优先遍历
解决方法3:
迭代
复杂度分析
递归
复杂度分析
二叉树基础概念:
树是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由 n(n>0)n(n>0) 个有限节点组成一个具有层次关系的集合。
把它叫做「树」是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
它具有以下的特点:
package leetCode.tree;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* REMARK 相同的树
*
* @author: mmb
* @date: 19-9-15
*/
public class TwoSameTreeSolution {
public static void main(String[] args){
TreeNode p = getATree();
// TreeNode q = getATree();
TreeNode q = getATreeV2();
System.out.println("result = " + isSameTree(p, q));
}
/**
* 比较两棵树是否相同
*/
public static boolean isSameTree(TreeNode p, TreeNode q){
List tree1AllNodes = getAllNodes(p);
List tree2AllNodes = getAllNodes(q);
System.out.println("tree1AllNodes = " + tree1AllNodes);
System.out.println("tree2AllNodes = " + tree2AllNodes);
return compareTwoTree(tree1AllNodes, tree2AllNodes);
}
/**
* 比较两棵树的结点列表
*/
private static boolean compareTwoTree(List tree1AllNodes, List tree2AllNodes) {
// 两棵树的节点要一样
if (tree1AllNodes.size() == tree2AllNodes.size()){
int countTime = 0;
int tree1NotNullCount = 0;
int tree2NotNullCount = 0;
Iterator iterator1 = tree1AllNodes.iterator();
Iterator iterator2 = tree2AllNodes.iterator();
// 逐个遍历两棵树的节点
while (iterator1.hasNext()){
Integer tree1Node = iterator1.next();
Integer tree2Node = iterator2.next();
// 两棵树的节点都不为空
if (tree1Node != null && tree2Node != null){
if (tree1Node.equals(tree2Node)){
countTime++;
continue;
} else {
break;
}
}
// 两棵树的节点都为空
else if (tree1Node == null && tree2Node == null) {
continue;
}
// 其中一棵树节点为空
else {
break;
}
}
// tree1的非空节点
for (Integer node : tree1AllNodes){
if (node != null){
tree1NotNullCount++;
}
}
// tree2的非空节点
for (Integer node : tree2AllNodes){
if (node != null){
tree2NotNullCount++;
}
}
// tree1和tree2和节点比较相同次数一样
if (tree1NotNullCount == countTime && tree2NotNullCount == countTime){
return true;
}
}
return false;
}
/**
* 获取所有节点数据
*/
private static List getAllNodes(TreeNode node){
// 前序遍历,递归获取所有节点信息
ArrayList treeNodes = new ArrayList<>();
if(node != null){
treeNodes.add(node.val);
if (node.left != null){
List allLeftNodes = getAllNodes(node.left);
treeNodes.addAll(allLeftNodes);
} else if (node.right != null){
treeNodes.add(null);
}
if (node.right != null){
List allRightNodes = getAllNodes(node.right);
treeNodes.addAll(allRightNodes);
}
}
return treeNodes;
}
/**
* 创建一棵树
*/
public static TreeNode getATree(){
TreeNode headNode = new TreeNode(1);
TreeNode leftNode = new TreeNode(2);
TreeNode rightNode = new TreeNode(3);
headNode.setLeft(leftNode);
headNode.setRight(rightNode);
return headNode;
}
public static TreeNode getATreeV2(){
TreeNode headNode = new TreeNode(1);
TreeNode leftNode = new TreeNode(2);
TreeNode rightNode = new TreeNode(3);
headNode.setLeft(leftNode);
headNode.setRight(rightNode);
return headNode;
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSameTree(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 isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
作者:guanpengchn
链接:https://leetcode-cn.com/problems/same-tree/solution/hua-jie-suan-fa-100-xiang-tong-de-shu-by-guanpengc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
终止条件与返回值:
执行过程:当满足终止条件时进行返回,不满足时分别判断左子树和右子树是否相同,其中要注意代码中的短路效应
时间复杂度:O(n),n 为树的节点个数
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
// p 和 q 均为 null时
if (p == null && q == null) return true;
// p 或 q 有一个为null时
if (q == null || p == null) return false;
if (p.val != q.val) return false;
return isSameTree(p.right, q.right) &&
isSameTree(p.left, q.left);
}
}
作者:gaohanghang
链接:https://leetcode-cn.com/problems/same-tree/solution/xiang-tong-de-shu-by-gaohanghang/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
时间复杂度:O(N),其中N是树中的节点数,因为每个节点只访问一次。
空间复杂度:O(log(N)):
在最佳情况下即completely balanced tree空间复杂度是O(log(N)),
在最坏情况下 completely unbalanced tree空间复杂度是O(N),和递归次数保持一致。
思路:从根开始,在每次迭代时将当前节点弹出deque。
然后执行与方法1中相同的检查:p 和 q 不为空,p.val 和 q.val 相等,如果检查正常,则push子节点。
class Solution {
public boolean check(TreeNode p, TreeNode q) {
// p and q are null
if (p == null && q == null) return true;
// one of p and q is null
if (q == null || p == null) return false;
if (p.val != q.val) return false;
return true;
}
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (!check(p, q)) return false;
// init deques
ArrayDeque deqP = new ArrayDeque();
ArrayDeque deqQ = new ArrayDeque();
deqP.addLast(p);
deqQ.addLast(q);
while (!deqP.isEmpty()) {
p = deqP.removeFirst();
q = deqQ.removeFirst();
if (!check(p, q)) return false;
if (p != null) {
// in Java nulls are not allowed in Deque
if (!check(p.left, q.left)) return false;
if (p.left != null) {
deqP.addLast(p.left);
deqQ.addLast(q.left);
}
if (!check(p.right, q.right)) return false;
if (p.right != null) {
deqP.addLast(p.right);
deqQ.addLast(q.right);
}
}
}
return true;
}
}
作者:gaohanghang
链接:https://leetcode-cn.com/problems/same-tree/solution/xiang-tong-de-shu-by-gaohanghang/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
时间复杂度 :O(N) 因为每个节点只访问一次
空间复杂度:O(log(N)), 在最佳情况下即completely balanced tree空间复杂度是O(log(N)),在最坏情况下 completely unbalanced tree空间复杂度是O(N)