1、257. 二叉树的所有路径
要求返回根节点到叶子节点的所有路径,这里用前序遍历就好。
每次递归前,都让字符串s加上当前节点的值和“->”,然后判断是否为叶子节点,如果是的话,说明这条路径是一个答案,因为最后多一个->,所以用substring去掉。
如果root是null,那么root.left和root.right可能会空指针异常。所以每次递归的时候都要做一下判断。
class Solution {
List<String> list = new ArrayList<>();
public List<String> binaryTreePaths(TreeNode root) {
String s = "";
pre(root, s);
return list;
}
public void pre(TreeNode root, String s){
s += root.val+"->";
if(root.left == null && root.right == null){
list.add(s.substring(0, s.length()-2));
return;
}
if(root != null && root.left != null) pre(root.left, s);
if(root != null && root.right != null) pre(root.right, s);
}
}
2、110. 平衡二叉树
我用的比较好想的方法,直接用非递归的方式前序遍历每个节点,在出栈的时候进行检查,检查每个节点的左右孩子最大高度差是否符合要求。
class Solution {
public boolean isBalanced(TreeNode root) {
LinkedList<TreeNode> stack = new LinkedList<>();
while(root != null || !stack.isEmpty()){
if(root != null){
stack.push(root);
root = root.left;
}
else{
//检查
TreeNode t = stack.pop();
if(Math.abs(H(t.left) - H(t.right)) > 1){
return false;
}
root = t.right;
}
}
return true;
}
public int H(TreeNode root){
if(root == null) return 0;
return Math.max(H(root.left), H(root.right))+1;
}
}
3、222. 完全二叉树的节点个数
直接遍历即可。
class Solution {
public int countNodes(TreeNode root) {
LinkedList<TreeNode> stack = new LinkedList<>();
int cnt = 0;
while(root != null || !stack.isEmpty()){
if(root != null){
cnt++;
stack.push(root);
root = root.left;
}
else{
TreeNode t = stack.pop();
root = t.right;
}
}
return cnt;
}
}
4、105. 从前序与中序遍历序列构造二叉树
前序:1 2 4 3 6 7
中序:4 2 1 6 3 7
首先,要确认根节点的值,根节点就是前序遍历的第一个节点。
于是我们得到根:1
然后在中序的数组中找到根,因为中序是 左根右 的顺序,所以根的左右两侧就是左子树
左:4 2
右:6 3 7
同样的,我们遍历左子树4 2,在前序中找到根,得到根是2,于是开始循环······
观察以上内容,我们可以这样做:找到前序遍历的节点,然后循环遍历中序数组,找到第i个元素是根节点,这时候继续递归寻找左子树,左子树的前序数组下标为1~i,中序数组为0~i-1;右子树的前序数组下标为i+1~len-1,中序数组为i+1~len-1
因为两个数组长度相同,所以判断退出条件写一个即可。
当然这样效率比较低,但是确实比较好理解一些。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return buildByPreAndIn(preorder, inorder);
}
public TreeNode buildByPreAndIn(int[] pre, int[] in){
if(pre.length == 0) return null;
//根节点
TreeNode root = new TreeNode(pre[0]);
for(int i = 0; i < in.length; i++){
if(root.val == in[i]){
//区分左右子树 in是 0~i-1 i+1 ~ len-1 pre是1 ~ i i+1 ~ len-1
root.left = buildByPreAndIn(Arrays.copyOfRange(pre, 1, i+1), Arrays.copyOfRange(in, 0, i));
root.right = buildByPreAndIn(Arrays.copyOfRange(pre, i+1, in.length), Arrays.copyOfRange(in, i+1, in.length));
break;
}
}
//每次返回根节点
return root;
}
}
class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
5、106. 从中序与后序遍历序列构造二叉树
跟上一个题区别不大,后序最后一个数就是根节点,也是从中序数组中找到根,然后又分成左右子树······
我们可以根据前序中序,也可以根据中序后序建树,但是不可以根据前序后序建树,因为前面两个方式,我们都可以通过前序或者后序明确得到根节点,然后根据中序划分左右子树,但是如果只有前序和后序,我们得到根节点之后,无法确定如何划分左右子树。
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
return buildByInAndPost(inorder, postorder);
}
public TreeNode buildByInAndPost(int[] in, int[] post){
if(in.length == 0) return null;
TreeNode root = new TreeNode(post[post.length - 1]);
for(int i = 0; i < in.length; i++){
if(in[i] == root.val){
root.left = buildByInAndPost(Arrays.copyOfRange(in, 0, i), Arrays.copyOfRange(post, 0, i));
root.right = buildByInAndPost(Arrays.copyOfRange(in, i+1, in.length), Arrays.copyOfRange(post, i, post.length-1));
break;
}
}
return root;
}
}
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}