0100 相同的树
题目:判断两棵树是否一样(节点值与树的结构都需要相同)
//100
public static boolean isSameTree(TreeNode p, TreeNode q) {
if (p==null&&q==null){
return true;
}
if (p==null&&q!=null){
return false;
}
if (p!=null&&q==null){
return false;
}
if (p.val==q.val){
return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}else{
return false;
}
}
0101 对称二叉树
给定一个二叉树,检查它是否是镜像对称的。
//101
public boolean isSymmetric(TreeNode root) {
if (root==null){
return true;
}
return isMirror(root.left,root.right);
}
public static boolean isMirror(TreeNode r1, TreeNode r2){
if (r1==null&&r2==null){
return true;
}
if (r1==null||r2==null){
return false;
}
if (r1.val==r2.val){
return isMirror(r1.left,r2.right)&&isMirror(r1.right,r2.left);
}else{
return false;
}
}
0107 二叉树层序遍历
题目:输出每一层的值
思路:广度优先搜索,板子题。
static LinkedList<List<Integer>>levelList;
public static List<List<Integer>> levelOrderBottom(TreeNode root) {
levelList= new LinkedList<>();
if (root==null){
return levelList;
}
Queue<TreeNode> q= new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
List <Integer>list = new LinkedList<>();
int size= q.size();
for (int i = 0; i < size ; i++) {
TreeNode t=q.poll();
list.add(t.val);
if (t.left!=null){
q.add(t.left);
}
if (t.right!=null){
q.add(t.right);
}
}
levelList.addFirst(list);
}
return levelList;
}
0111 二叉树最小深度
给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
//111
public static int minDepth(TreeNode root) {
if (root==null){
return 0;
}
if (root.left==null&&root.right==null){
return 1;
}
if (root.left==null){
return 1+minDepth(root.right);
}
if (root.right==null){
return 1+minDepth(root.left);
}
return 1+Math.min(minDepth(root.left),minDepth(root.right));
}
0112 路径总和
题目:给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
public boolean hasPathSum(TreeNode root, int sum) {
if (root==null){
return false;
}
sum-=root.val;
if (sum==0&&root.left==null&&root.right==null){
return true;
}
return hasPathSum(root.left,sum)||hasPathSum(root.right,sum);
}
0226 翻转二叉树
题目:将节点的所有左右节点互换。
public static TreeNode invertTree(TreeNode root) {
if (root==null){
return root;
}
if (root.left==null&&root.right==null){
return root;
}
if (root.left==null){
root.left=root.right;
root.right=null;
}else if (root.right==null){
root.right=root.left;
root.left=null;
}
if (root.left!=null&&root.right!=null){
TreeNode t= root.left;
root.left=root.right;
root.right=t;
}
invertTree(root.left);
invertTree(root.right);
return root;
}
0235 二叉搜索树的公共祖先
**公共祖先:**对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u和v的祖先且x的深度尽可能大。在这里,一个节点也可以是它自己的祖先。
public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
int rootVal= root.val;
int pVal=p.val;
int qVal=q.val;
if (p.val<root.val&&q.val<root.val){
return lowestCommonAncestor(root.left,p,q);
}else if (p.val>root.val&&q.val>root.val){
return lowestCommonAncestor(root.right,p,q);
}else{
return root;
}
}
0257 二叉树的所有路径
**题目:**给定一个二叉树,返回所有从根节点到叶子节点的路径。
注意:path是字符串类型,作为参数传递给construct_paths方法,是传递地址的拷贝。
public static List<String> binaryTreePaths(TreeNode root) {
LinkedList<String> paths = new LinkedList();
constructPath(root, "", paths);
return paths;
}
public static void constructPath
(TreeNode root, String path, List<String> paths){
if (root!=null){
path += Integer.toString(root.val);
if (root.left==null&&root.right==null){
paths.add(path);
}else{
path+="->";
constructPath(root.left,path,paths);
constructPath(root.right,path,paths);
}
}
}
//强行回溯,用list。有很多改进方案
static LinkedList<LinkedList<Integer>>pathList;
public static List<String> binaryTreePaths(TreeNode root) {
pathList= new LinkedList<>();
List<String>answer= new LinkedList<>();
if (root==null){
return answer;
}
backtrace(root,new LinkedList<>());
for (int i = 0; i < pathList.size() ; i++) {
LinkedList<Integer>temp= pathList.get(i);
String ans= new String();
// System.out.println(temp.size());
for (int j = 0; j < temp.size() ; j++) {
if (j==0){
ans+=Integer.toString(temp.get(j));
}else{
ans+="->"+Integer.toString(temp.get(j));
}
}
answer.add(ans);
}
return answer;
}
public static void backtrace(TreeNode root, LinkedList<Integer>list){
if (root.left==null&&root.right==null){
list.add(root.val);
pathList.add(new LinkedList<>(list));
list.removeLast();
return;
}
list.add(root.val);
if (root.left!=null) {
backtrace(root.left, list);
}
if (root.right!=null) {
backtrace(root.right, list);
}
list.removeLast();
}
0404 左叶子之和
题目:求树的所有左叶子节点
//404
public static int sumOfLeftLeaves(TreeNode root) {
if (root==null){
return 0;
}
if (root.left==null){
return sumOfLeftLeaves(root.right);
}
if (root.left.left==null&&root.left.right==null){
return root.left.val+sumOfLeftLeaves(root.right);
}
return sumOfLeftLeaves(root.left)+sumOfLeftLeaves(root.right);
}
0437 路径总和
给定一个二叉树,它的每个结点都存放着一个整数值。找出路径和等于给定数值的路径总数。
public static int pathSum(TreeNode root, int sum) {
if (root==null){
return 0;
}
return Sum(root,sum)+pathSum(root.left,sum)+pathSum(root.right,sum);
}
public static int Sum(TreeNode root, int sum){
if(root==null){
return 0;
}
sum-=root.val;
if (sum==0){
return 1+Sum(root.left,sum)+Sum(root.right,sum);
}
return Sum(root.left,sum)+Sum(root.right,sum);
}
0501 二叉搜索树中的众数
题目:求BST的众数
思路:中序遍历BST为递增序列,转化为求递增序列的众数。
List<Integer>list= new ArrayList<>();
int preval=0; int currtimes=0; int maxtimes=0;
public int[] findMode(TreeNode root) {
inorder(root);
int ans[] = new int[list.size()];
for (int i = 0; i < list.size() ; i++) {
ans[i]=list.get(i);
}
return ans;
}
public void inorder(TreeNode root){
if(root != null){
inorder(root.left);
if (root.val==preval){
currtimes++;
}else{
preval=root.val;
currtimes=1;
}
if (currtimes==maxtimes){
list.add(root.val);
}
if (currtimes>maxtimes){
maxtimes=currtimes;
list.clear();
list.add(preval);
}
inorder(root.right);
}
}
0538 把二叉搜索树转换为累加树
题目:给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。
思路:反序遍历就是降序,一次遍历即可
int count=0;
public TreeNode convertBST(TreeNode root) {
reverseOrder(root);
return root;
}
public void reverseOrder(TreeNode root){
if (root!=null){
reverseOrder(root.right);
count+=root.val;
root.val=count;
reverseOrder(root.left);
}
}
0543 二叉树的直径
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
int ans=0;
public int diameterOfBinaryTree(TreeNode root) {
if (root==null){
return 0;
}
depth(root);
return ans;
}
public int depth(TreeNode node) {
if (node == null) return 0;
int L = depth(node.left);
int R = depth(node.right);
ans = Math.max(ans, L+R);//直径
return Math.max(L, R) + 1;//深度
}
//更加清晰的思路,左右最大深度之和为直径。但是时间复杂度爆炸,只为解释一下上面解法
int ans=0;
public int diameterOfBinaryTree(TreeNode root) {
if (root == null) {
return 0;
}
preorder(root);
return ans;
}
public void preorder(TreeNode root){
if (root!=null){
preorder(root.left);
int L= maxdepth(root.left);
int R= maxdepth(root.right);
ans=Math.max(ans,L+R);
preorder(root.right);
}
}
public int maxdepth (TreeNode root){
if (root==null){
return 0;
}
return 1+Math.max(maxdepth(root.left),maxdepth(root.right));
}
0563 二叉树的坡度
题目:一个树的节点的坡度定义即为,该节点左子树的结点之和和右子树结点之和的差的绝对值。空结点的的坡度是0。
思路:想到后序遍历,存储左子树的结点之和和右子树结点和,再计算
//法一
int tilt=0;
public int findTilt(TreeNode root) {
traverse(root);
return tilt;
}
public int traverse(TreeNode root)
{
if(root==null )
return 0;
int left=traverse(root.left);
int right=traverse(root.right);
tilt+=Math.abs(left-right);
return left+right+root.val;
}
//法二
/*两次遍历*/
int answer=0;
public int findTilt(TreeNode root) {
if (root==null){
return 0;
}
backorder(root);
backorderMinus(root);
return answer;
}
public void backorderMinus(TreeNode root){
if(root != null){
backorderMinus(root.left);
backorderMinus(root.right);
if (root.left==null&&root.right!=null){
answer+=Math.abs(root.right.val);
}else if (root.left!=null&&root.right==null){
answer+=Math.abs(root.left.val);
}else if (root.left!=null&&root.right!=null){
answer+=Math.abs(root.left.val-root.right.val);
}
}
}
public void backorder(TreeNode root){
if(root != null){
backorder(root.left);
backorder(root.right);
if (root.left==null&&root.right!=null){
root.val+=root.right.val;
}else if (root.left!=null&&root.right==null){
root.val+=root.left.val;
}else if (root.left!=null&&root.right!=null){
root.val+=root.left.val+root.right.val;
}
}
}
0572 另一个树的子树
题目:给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。
思路:如果s和t的val相等,判断是否为sameTree;如果不等,再判断s的左右子树
public static boolean isSameTree(TreeNode p, TreeNode q) {
if (p==null&&q==null){
return true;
}
if (p==null&&q!=null){
return false;
}
if (p!=null&&q==null){
return false;
}
if (p.val==q.val){
return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}else{
return false;
}
}
public boolean isSubtree(TreeNode s, TreeNode t) {
if (t==null){
return true;
}
if (s==null){
return false;
}
if (s.val!=t.val){
return isSubtree(s.left,t)||isSubtree(s.right,t);
}else{
return isSameTree(s,t)||isSubtree(s.left,t)||isSubtree(s.right,t);
}
}
0617 合并二叉树
题目:给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
思路:以t1为主体,递归建树
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if (t1==null){
return t2;
}
if (t2==null){
return t1;
}
t1.val=t1.val+t2.val;
t1.left = mergeTrees(t1.left, t2.left);
t1.right = mergeTrees(t1.right, t2.right);
return t1;
}
0637 二叉树的层平均值
题目:给定一个非空二叉树, 返回一个由每层节点平均值组成的数组.
思路:层序遍历,BFS,与0107类似。
public List<Double> averageOfLevels(TreeNode root) {
List<Double>list= new LinkedList<>();
if (root==null){
return list;
}
Queue<TreeNode>q= new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
double sum=0;
int size= q.size();
for (int i = 0; i < size; i++) {
TreeNode t = q.poll();
sum+=t.val;
if (t.left!=null){
q.add(t.left);
}
if (t.right!=null){
q.add(t.right);
}
}
list.add(sum/size);
}
return list;
}
0108 将有序数组转化为BST
思路:二分查找,递归建树
public TreeNode sortedArrayToBST(int[] nums) {
// 左右等分建立左右子树,中间节点作为子树根节点,递归该过程
return nums == null ? null : buildTree(nums, 0, nums.length - 1);
}
private TreeNode buildTree(int[] nums, int l, int r) {
if (l > r) {
return null;
}
int m = l + (r - l) / 2;
TreeNode root = new TreeNode(nums[m]);
root.left = buildTree(nums, l, m - 1);
root.right = buildTree(nums, m + 1, r);
return root;
}