引
今天在leetcode上刷完了常见的树的遍历的题,就来总结下规律。
二叉树
层次遍历
该题目对应于 leetcode:102 二叉树的层次遍历
https://leetcode-cn.com/problems/binary-tree-level-order-traversal/description/
思路:
既然是层次遍历,就选择使用BFS广度优先搜索来解决,BFS的核心就是队列。
从根开始,如果有左孩子,就加入到队列中;如果有右孩子,就加入到队列中。
先加入左孩子再加入右孩子,只要队列中有节点,就一直循环。
代码如下:
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> lists = new ArrayList<>();
if(root == null) return lists;
queue.add(root);
while(!queue.isEmpty()){
List<Integer> list = new ArrayList<>();
int count = queue.size();
for(int i=0;i<count;i++){
TreeNode now = queue.poll();
list.add(now.val);
if(now.left != null){
queue.add(now.left);
}
if(now.right != null){
queue.add(now.right);
}
}
lists.add(list);
}
return lists;
}
层次遍历 II
该题目对应于 leetcode:107 二叉树的层次遍历 II
https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/
这道题和上一道的区别在于,这道题是从下往上的层次遍历。
解法一:
最省事的解法,就是把102的代码的lists结果用工具类Collections.reverse(lists)即可。
public List<List<Integer>> levelOrderBottom(TreeNode root){
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> lists = new ArrayList<>();
if(root == null) return lists;
queue.add(root);
while(!queue.isEmpty()){
List<Integer> list = new ArrayList<>();
int count = queue.size();
for(int i=0;i<count;i++){
TreeNode now = queue.poll();
list.add(now.val);
if(now.left != null){
queue.add(now.left);
}
if(now.right != null){
queue.add(now.right);
}
}
lists.add(list);
}
Collections.reverse(lists);
return lists;
}
解法二:
DFS,深度优先搜索。
public List<List<Integer>> levelOrderBottom(TreeNode root){
List<List<Integer>> result = new ArrayList<>();
helper(result,root,0);
return result;
}
private void helper(List<List<Integer>> result, TreeNode root, int depth) {
if (root==null) return;
if (result.size()==depth) result.add(0, new ArrayList<>());
result.get(result.size() - depth - 1).add(root.val);
helper(result, root.left, depth + 1);
helper(result, root.right, depth + 1);
}
前序遍历
该题目对应于 leetcode:144 二叉树的前序遍历
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
思路:
借助栈的特性,先将根节点加入到栈中,然后检查左子树、右子树是否为空。
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
List<Integer> result = new ArrayList<>();
if(root == null) return result;
stack.push(root);
while(!stack.isEmpty()){
TreeNode now = stack.pop();
result.add(now.val);
// 注意,因为是栈结构,所以要先放入右子节点,然后再放入左子节点
if(now.right != null){
stack.push(now.right);
}
if(now.left != null){
stack.push(now.left);
}
}
return result;
}
中序遍历
该题目对应于 leetcode:94 二叉树的中序遍历
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
思路:中序遍历,即左根右。还是借助栈结构。那么,我们就要换一种思路,用一个指针去遍历,看左子节点有没有孩子,有的话就加入栈中,没有,就将父节点取出,将值加入到数组中,然后再指向右子节点。
public List<Integer> inorderTraversal(TreeNode root) {
Stack<Integer> stack = new Stack<>();
List<Integer> result = new ArrayList<>();
if(root == null) return result;
TreeNode now = root;
while(now != null && !stack.isEmpty()){
if(now != null){
stack.push(now);
now = now.left;
} else {
now = stack.pop();
result.add(now.val);
now = now.right;
}
}
return result;
}
后序遍历
该题目对应于 leetcode:145 二叉树的后序遍历
https://leetcode-cn.com/problems/binary-tree-postorder-traversal/
思路:和前序遍历类似,结果反转。
public List<Integer> postorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
List<Integer> output = new ArrayList<>();
if (root == null) return output;
stack.add(root);
while (!stack.isEmpty()) {
TreeNode now = stack.pop();
output.add(now.val);
if (now.left != null) {
stack.push(now.left);
}
if (now.right != null) {
stack.push(now.right);
}
}
Collections.reverse(output);
return output;
}
深度
最大深度
该题目对应于 leetcode:104 二叉树的最大深度
https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/
思路:DFS递归,递归终止条件:节点为空。
public int maxDepth(TreeNode root) {
if(root == null) {
return 0;
} else {
int left_depth = maxDepth(root.left);
int right_depth = maxDepth(root.right);
return Math.max(left_depth,right_depth) + 1;
}
}
最小深度
该题目对应于 leetcode:111 二叉树的最小深度
https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/submissions/
思路:DFS递归。
public int minDepth(TreeNode root) {
if(root == null) return 0;
if(root.left == null && root.right == null) return 1;
int min_depth = Integer.MAX_VALUE;
if(root.left != null){
min_depth = Math.min(min_depth,minDepth(root.left));
}
if(root.right != null){
min_depth = Math.min(min_depth,minDepth(root.right));
}
return min_depth + 1;
}
N叉树
层次遍历
该题目对应于 leetcode:429 N叉树的层序遍历
https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/submissions/
思路:一般只有层次遍历才会使用到队列,即BFS广度优先搜索。
public List<List<Integer>> levelOrder(Node root) {
Queue<Node> queue = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
if(root == null) return result;
queue.add(root);
while(!queue.isEmpty()){
int count = queue.size();
List<Integer> list = new ArrayList<>();
for(int i=0;i<count;i++){
Node now = queue.poll();
list.add(now.val);
for(Node child : now.children){
queue.add(child);
}
}
result.add(list);
}
return result;
}
前序遍历
该题目对应于 leetcode:589 N叉树的前序遍历
https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal/
思路:借助栈结构,类似于二叉树的前序遍历。
public List<Integer> preorder(Node root) {
Stack<Node> stack = new Stack<>();
List<Integer> result = new ArrayList<>();
if(root == null) return result;
stack.push(root);
while(!stack.isEmpty()){
Node now = stack.pop();
result.add(now.val);
List<Node> nodes = now.children;
for(int i=nodes.size()-1;i>=0;i--){
stack.push(nodes.get(i));
}
}
return result;
}
后序遍历
该题目对应于 leetcode:590 N叉树的后序遍历
https://leetcode-cn.com/problems/n-ary-tree-postorder-traversal/
思路:类似于前序遍历,借助栈结构。
public List<Integer> postorder(Node root) {
Stack<Node> stack = new Stack<>();
List<Integer> result = new ArrayList<>();
if(root == null) return result;
stack.push(root);
while(!stack.isEmpty()){
Node now = stack.pop();
result.add(0,now.val);
for(Node child : now.children){
stack.push(child);
}
}
return result;
}
最大深度
该题目对应于 leetcode:559 N叉树的最大深度
https://leetcode-cn.com/problems/maximum-depth-of-n-ary-tree/submissions/
思路:利用队列,迭代。
public int maxDepth(Node root) {
Queue<Node> queue = new LinkedList<>();
if(root == null) return 0;
queue.add(root);
int max = 0;
while(!queue.isEmpty()){
max++;
int count = queue.size();
while(count-- >0){
Node now = queue.poll();
for(Node child : now.children){
queue.add(child);
}
}
}
return max;
}