关于这前十道题,总结出来的一点就是递归,树的问题递归来写是非常简单,因为递归的话方便回到父节点。
- maximum-depth-of-binary-tree
题目描述
求给定二叉树的最大深度,
最大深度是指树的根结点到最远叶子结点的最长路径上结点的数量。
这个就可以直接递归,求整棵树的最大深度可以看出求左右两颗子树的最大深度的问题,这样就把问题划分成了两个子问题。
public static class TreeNode {
private int val;
private TreeNode left;
private TreeNode right;
TreeNode(int x) {
this.val = x;
}
}
public static int maxDepth(TreeNode root) {
if(root == null) {
return 0;
}
if(root.left == null && root.right == null) {
return 0;
}
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
- same-tree
题目描述
给出两个二叉树,请写出一个判断两个二叉树是否相等的函数。
判断两个二叉树相等的条件是:两个二叉树的结构相同,并且相同的节点上具有相同的值。
这个也是可以递归,就是想成判断两棵树是否相等,就去判断他的左右节点一样不,判断都有没有左右子树和判断左右子树的值一样不一样。
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);
}
- unique-binary-search-trees
题目描述
给定一个值n,能构建出多少不同的值包含1…n的二叉搜索树(BST)?
例如
给定 n = 3, 有五种不同的二叉搜索树(BST)
首先知道二叉搜索树的概念,对于任一个节点,它的左子树都比他小,右子树都比他大。二叉树中序遍历结果是升序的就是二叉搜索树。
当n = 3 时,有五种不同的二叉搜索树
根据二叉搜索树的概念,可以得到递归的思路,就是把每次的n规模的节点拆成左边i - 1个右边n - i个
public static int numTrees(int n) {
if(n == 0 || n == 1) {
return 1;
}
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += numTrees(i - 1) * numTrees(n - i);
}
return sum;
}
//在递归的过程中有重复性的解,所以可以改成动态规划
public static int numTreeDp(int n) {
int[] dp = new int[n + 1];
dp[0] = dp[1] = 1;
for (int i = 2 ;i <= n;i ++) {
for (int j = 1; j <= i; j++) {
dp[i] += dp[j-1] * dp[i-j];
}
}
return dp[n];
}
- populating-next-right-pointers-in-each-node
题目描述
给定一个二叉树
struct TreeLinkNode {
TreeLinkNode *left;
TreeLinkNode *right;
TreeLinkNode *next;
}
填充所有节点的next指针,指向它右兄弟节点。如果没有右兄弟节点,则应该将next指针设置为NULL。
初始时,所有的next指针都为NULL
注意:
你只能使用常量级的额外内存空间
可以假设给出的二叉树是一个完美的二叉树(即,所有叶子节点都位于同一层,而且每个父节点都有两个孩子节点)。
//递归解法
public static void connect(TreeLinkNode root) {
if(root == null) {
return ;
}
if(root.left != null && root.right != null) {
root.left.next = root.right;
}
if(root.next != null && root.right != null) {
root.right.next = root.next.left;
}
connect(root.left);
connect(root.right);
}
//非递归
public static void connect2(TreeLinkNode root) {
if(root == null) {
return;
}
TreeLinkNode p = root;
TreeLinkNode q = null;
while(p.left != null) {
q = p;
while(q != null) {
q.left.next = q.right;
if(q.next != null) {
q.right.next = q.next.left;
}
q = q.next;
}
p = p.left;
}
}
- balanced-binary-tree
题目描述
判断给定的二叉树是否是平衡的
在这个问题中,定义平衡二叉树为每个节点的左右两个子树高度差的绝对值不超过1的二叉树
判读一颗二叉树是否是平衡二叉树。二叉树的每一个节点的左子树和右子树的高度差不超过1。面对二叉树中的高度套路化,可以利用递归,列出可能性,设计递归返回思路,返回信息类型(需要的信息柔和成一个类)。
public class Tree{
private int val;
private Tree left;
private Tree right;
public Tree(int val) {
this.val = val;
}
}
public static class Height{
private int h;
private boolean isB;
public Height(int h,boolean isB) {
this.h = h;
this.isB = isB;
}
}
public static Height process(Tree head) {
if(head == null) {
return new Height(0, true);
}
Height left = process(head.left);
if(!left.isB) {
return new Height(0, false);
}
Height right = process(head.right);
if(!right.isB) {
return new Height(0, false);
}
if(Math.abs(left.h - right.h) > 1) {
return new Height(0,false);
}
return new Height(Math.max(left.h, right.h) + 1, true);
}
public static boolean isB(Tree head) {
return process(head).isB;
}
- binary-tree-inorder-traversal
题目描述:
非递归中序遍历一颗二叉树
public ArrayList<Integer> inorderTraversal(TreeNode root) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
while(!stack.isEmpty() || root != null) {
if(root != null) {
stack.push(root);
root = root.left;
}else {
root = stack.pop();
arrayList.add(root.val);
root = root.right;
}
}
return arrayList;
}
- binary-tree-preorder-traversal
题目描述:
非递归先序遍历一颗二叉树
public ArrayList<Integer> preorderTraversal(TreeNode root) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
if (root != null) {
stack.add(root);
while (!stack.isEmpty()) {
root = stack.pop();
arrayList.add(root.val);
if (root.right != null) {
stack.push(root.right);
}
if (root.left != null) {
stack.push(root.left);
}
}
}
return arrayList;
}
- path-sum
题目描述
给定一个二叉树和一个值sum,判断是否有从根节点到叶子节点的节点值之和等于sum的路径,
例如:
给出如下的二叉树,sum=22,
public boolean hasPathSum(TreeNode root, int sum) {
return isTOrF(root, sum, 0);
}
//递归之前,先想清楚递归的条件再写。递归的basecase是写递归的关键
private boolean isTOrF(TreeNode root, int sum, int res) {
// TODO Auto-generated method stub
if (root == null) {
return false;
}
if(root.left == null && root.right == null && sum == res + root.val) {
return true;
}
return isTOrF(root.left, sum, res + root.val) || isTOrF(root.right, sum, res + root.val);
}
- binary-tree-level-order-traversal
题目描述
给定一个二叉树,返回该二叉树层序遍历的结果,(从左到右,一层一层地遍历)
例如:
给定的二叉树是{3,9,20,#,#,15,7},
该二叉树层序遍历的结果是
[↵ [3],↵ [9,20],↵ [15,7]↵]
public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
ArrayList<ArrayList<Integer>> arrayLists = new ArrayList<ArrayList<Integer>>();
if(root == null) {
return arrayLists;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
//这个题的关键在于获得每层的节点个数
while(!queue.isEmpty()) {
int num = queue.size();//获得每层的节点个数
ArrayList<Integer> arrayList = new ArrayList<Integer>();
for (int i = 0; i < num; i++) {
root = queue.peek();
if(root.left != null) {
queue.offer(root.left);
}
if(root.right != null) {
queue.offer(root.right);
}
arrayList.add(queue.poll().val);
}
arrayLists.add(arrayList);
}
return arrayLists;
}
- symmetric-tree
题目描述
给定一棵二叉树,判断琪是否是自身的镜像(即:是否对称)
递归给的这棵树,其中一个递归左边的,另一个递归右边的。
public boolean isSymmetric(TreeNode root) {
return root(root,root);
}
public boolean root(TreeNode left,TreeNode right) {
if(left == null && right == null) {
return true;
}
if(left == null || right == null) {
return false;
}
return left.val == right.val && root(left.left,right.right) && root(left.right,right.left);
}