【递归思想三部曲】
- 确定递归函数的参数和返回值
- 确定终止条件
- 确定单层递归的逻辑
144. 二叉树的前序遍历
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null) return res;
preOrder(root);
return res;
}
private void preOrder(TreeNode t) {
if(t == null) return;
res.add(t.val);
if(t.left != null) preOrder(t.left);
if(t.right != null) preOrder(t.right);
}
}
94. 二叉树的中序遍历
java
/**
* Definition for a binary tree node.
* public 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;
* }
*/
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root == null) return res;
inOrder(root);
return res;
}
private void inOrder(TreeNode t) {
if(t == null) return;
if(t.left != null) inOrder(t.left);
res.add(t.val);
if(t.right != null) inOrder(t.right);
}
}
145. 二叉树的后序遍历
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root == null) return res;
postOrder(root);
return res;
}
private void postOrder(TreeNode t) {
if(t == null) return;
if(t.left != null) postOrder(t.left);
if(t.right != null) postOrder(t.right);
res.add(t.val);
}
}
102. 二叉树的层序遍历
- 时间复杂度:O(n),其中 n 为二叉树的节点个数,每个节点只会遍历一遍。
- 空间复杂度:O(n)。队列中元素不超过 n 个。
只需要注意队列的实现以及使用即可。
这个是手写队列。
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
TreeNode[] q = new TreeNode[2010];
int hh = 0,tt = -1;
if(root == null) return res;
q[++tt] = root;
while(hh <= tt) {
int len = tt - hh + 1;
List<Integer> tmp = new ArrayList<>();
while(len -- > 0) {
TreeNode t = q[hh++];
tmp.add(t.val);
if(t.left != null) q[++tt] = t.left;
if(t.right != null) q[++tt] = t.right;
}
res.add(tmp);
}
return res;
}
}
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if(root == null) return res;
LinkedList<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()) {
int curSize = q.size();
List<Integer> tmp = new ArrayList<>();
while(curSize -- > 0) {
TreeNode t = q.poll();
tmp.add(t.val);
if(t.left != null) q.offer(t.left);
if(t.right != null) q.offer(t.right);
}
res.add(tmp);
}
return res;
}
}
226. 翻转二叉树
交换指针,而不是交换节点值。
使用前序遍历,对其左右子树直接交换即可。
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null) return null;
traversal(root);
return root;
}
private void traversal(TreeNode cur) {
if(cur == null) return;
TreeNode tmp = new TreeNode();
tmp = cur.left;
cur.left = cur.right;
cur.right = tmp;
traversal(cur.left);
traversal(cur.right);
}
}
即使左右子树一个为空,那也可以交换。
所以这里层序遍历,一层一层进行交换也是可以的
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null) return null;
LinkedList<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()) {
int curSize = q.size();
while(curSize -- > 0) {
TreeNode t = q.poll();
if(t.left != null) q.offer(t.left);
if(t.right != null) q.offer(t.right);
TreeNode tmp = t.left;
t.left = t.right;
t.right = tmp;
}
}
return root;
}
}
101. 对称二叉树
- 为什么要后续遍历?
我们要去判断一棵树是否对称,那么必然是要判断出该树的所有子树都是对称的;这也就意味着最后再去判断根节点:左 右 中。
在compare逻辑中,是一个父节点与其左右孩子节点的逻辑。无非都空、左空、右空、值不相等、相等的情况。
如果是前4种情况,可以直接判断结果;最后一种结果就要去看其子节点,就递归下去了:先看子节点最后传导父节点判断结果。
- 其实是比较两个子树,是否可以翻转,这个说法成立不成立。
从理解上是这样,但就是对称。要比较左右子树是否完全对称,再去判断整棵树是否对称。
javascript
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
return traversal(root.left, root.right);
}
private boolean traversal(TreeNode left, TreeNode right) {
if(left == null && right == null) return true;
if(left != null && right == null) return false;
if(left == null && right != null) return false;
if(left.val != right.val) return false;
boolean out = traversal(left.left, right.right);
boolean in = traversal(left.right, right.left);
return in && out;
}
}
104. 二叉树的最大深度
就是求解一个树的高度问题,求最高的子树的高度。
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
return getDepth(root);
}
private int getDepth(TreeNode cur) {
if(cur == null) return 0;
int left = getDepth(cur.left);
int right = getDepth(cur.right);
return Math.max(left, right) + 1;
}
}
使用层序求解,一共多少层,就是最大深度。
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
LinkedList<TreeNode> q = new LinkedList<>();
q.offer(root);
int res = 0;
while(!q.isEmpty()) {
int curSize = q.size();
while(curSize-- > 0) {
TreeNode t = q.poll();
if(t.left != null) q.offer(t.left);
if(t.right != null) q.offer(t.right);
}
res++; // 一层节点一计算
}
return res;
}
}
111. 二叉树的最小深度
同理:就是求解一个树的高度问题,求最高的子树的高度。
那么这里认为,null 子树不算,计算另一个子树高度。
- 为什么要这样计算?
null 节点不算是叶子节点,所以计算的是叶子节点的深度。
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
if(root == null) return 0;
return getDepth(root);
}
private int getDepth(TreeNode cur) {
if(cur == null) return 0;
int left = getDepth(cur.left);
int right = getDepth(cur.right);
if(cur.left == null) return right + 1;
if(cur.right == null) return left + 1;
return Math.min(left, right) + 1;
}
}
层序遍历求解,不过特殊情况就是:这一层结束了,并且没有下一层了,所以必须 res++
java
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
if(root == null) return 0;
LinkedList<TreeNode> q = new LinkedList<>();
q.offer(root);
int res = 0;
while(!q.isEmpty()) {
int curSize = q.size();
while(curSize-- > 0) {
TreeNode t = q.poll();
if(t.left == null && t.right == null) {
res++;
return res;
}
if(t.left != null) q.offer(t.left);
if(t.right != null) q.offer(t.right);
}
res++; // 一层节点一计算
}
return res;
}
}