Java一套拳法刷掉n个遍历树的问题

我不害怕曾經練過一萬種踢法的人,但我害怕一種踢法練過一萬次的人(by 叶师傅的徒弟Bruce Lee)
在这里插入图片描述

树的遍历(Traversal)

如下图, 三种遍历方式, 可用同一种递归思想实现
在这里插入图片描述

1. 144. 先序遍历(PreOrder, 按照先访问根节点的顺序)

示例 11
	  \
	   2
	  /
	3   

输入:root = [1,null,2,3]
输出:[1,2,3]

解法

/*
 * @lc app=leetcode.cn id=144 lang=java
 *
 * [144] 二叉树的前序遍历
 */

// @lc code=start
/**
 * 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<Integer> preorderTraversal(TreeNode root) {
    
    
        List<Integer> list = new ArrayList<>();
        dfs(root, list);
        return list;
    }

    private void dfs(TreeNode root, List<Integer> list) {
    
    
        if (root == null) return;
        list.add(root.val);
        dfs(root.left, list);
        dfs(root.right, list);
    }
}
// @lc code=end

2. 94 中序遍历(InOrder, 按照根节点在中间访问的顺序)

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

示例:
	1
	  \
	   2
	  /
	3   

输入:root = [1,null,2,3]
输出:[1,3,2]

解法

class Solution {
    
    
    public List<Integer> inorderTraversal(TreeNode root) {
    
    
        List<Integer> list = new ArrayList<>();
        dfs(root, list);

        return list;
    }

    private void dfs(TreeNode root, List<Integer> list) {
    
    
        if (root == null) return;
        dfs(root.left, list);
        list.add(root.val);
        dfs(root.right, list);
    }
}

3. 145 后续遍历(PosterOrder, 按照根节点在后面访问的顺序)

示例:

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [3,2,1]

解法

class Solution {
    
    
    public List<Integer> postorderTraversal(TreeNode root) {
    
    
        List<Integer> list = new ArrayList<>();
        dfs(root, list);
        return list;
    }

    private void dfs(TreeNode root, List<Integer> list) {
    
    
        if (root == null) return;
        dfs(root.left, list);
        dfs(root.right, list);
        list.add(root.val);
    }
}

4. 100. 相同的树

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
在这里插入图片描述

输入:p = [1,2,3], q = [1,2,3]
输出:true

解法

class Solution {
    
    
    public boolean isSameTree(TreeNode p, TreeNode q) {
    
    
        if ((p == null && q != null) || (p != null && q == null)) return false;
        if (p == null && q == null) return true;
        return p.val == q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
}

5. 226 翻转二叉树

翻转一棵二叉树。


示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9
输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

备注:
这个问题是受到 Max Howell 的 原问题 启发的 :

谷歌:我们90%的工程师使用您编写的软件(Homebrew),但是您却无法在面试时在白板上写出翻转二叉树这道题,这太糟糕了。
在这里插入图片描述

class Solution {
    
    
    public TreeNode invertTree(TreeNode root) {
    
    
        if (root == null) return root;
        TreeNode left = root.left;
        TreeNode right = root.right;
        root.left = invertTree(right);
        root.right = invertTree(left);
        return
    }
}

6. 590. N 叉树的后序遍历

给定一个 N 叉树,返回其节点值的 后序遍历 。

N 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

进阶:

递归法很简单,你可以使用迭代法完成此题吗?

示例 1:
在这里插入图片描述

输入:root = [1,null,3,2,4,null,5,6]
输出:[5,6,3,2,4,1]

解法

/*
 * @lc app=leetcode.cn id=590 lang=java
 *
 * [590] N 叉树的后序遍历
 */

// @lc code=start
/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    
    
    public List<Integer> postorder(Node root) {
    
    
        List<Integer> list = new ArrayList<>();
        dfs(root, list);

        return list;
    }

    private void dfs(Node root, List<Integer> list) {
    
    
        if (root == null) return;
        for(Node node: root.children) {
    
    
            dfs(node, list);
        }
        list.add(root.val);
    }
}
// @lc code=end

7. 103. 二叉树的锯齿形层序遍历

给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

例如:

给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回锯齿形层序遍历如下:

[
  [3],
  [20,9],
  [15,7]
]

解法:

/*
 * @lc app=leetcode.cn id=103 lang=java
 *
 * [103] 二叉树的锯齿形层序遍历
 */

// @lc code=start
/**
 * 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>> zigzagLevelOrder(TreeNode root) {
    
    
        List<List<Integer>> result = new ArrayList<>();
        if (root == null) {
    
    
            return result;
        }
        boolean isLeftToRight = true;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
    
    
            Deque<Integer> levelDeque = new LinkedList<>();
            int size = queue.size();
            for (int i = 0; i < size; i++) {
    
    
                TreeNode node = queue.poll();
                if (isLeftToRight) {
    
    
                    levelDeque.offerLast(node.val);
                } else {
    
    
                    levelDeque.offerFirst(node.val);
                }
                if (node.left != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }

            result.add(new LinkedList<Integer>(levelDeque));
            isLeftToRight = !isLeftToRight;
        }

        return result;
    }
}
// @lc code=end

8. 230. 二叉搜索树中第K小的元素

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

示例 13
     / \
    1   4
     \
      2  
输入:root = [3,1,4,null,2], k = 1
输出:1

中序遍历

class Solution {
    
    
    public int kthSmallest(TreeNode root, int k) {
    
    
        List<Integer> list = new ArrayList<>();
        dfs(root, k, list);

        return list.get(k - 1);
    }

    private void dfs(TreeNode root, int k, List<Integer> list) {
    
    
        if (root == null || list.size() == k) return;
        dfs(root.left, k, list);
        list.add(root.val);
        dfs(root.right, k, list);
    }
}

9. 102. 二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例:
二叉树:[3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回其层序遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

递归 + 前序遍历的解法,记录每一层的高度值。

class Solution {
    
    
    public List<List<Integer>> levelOrder(TreeNode root) {
    
    
        List<List<Integer>> result = new ArrayList<>();
        dfs(root, 0, result);

        return result;
    }

    private void dfs(TreeNode root, int level, List<List<Integer>> result) {
    
    
        if (root == null) return;
        if (result.size() == level) {
    
    
            result.add(new ArrayList<Integer>());
        }
        result.get(level).add(root.val);
        dfs(root.left, level + 1, result);
        dfs(root.right, level + 1, result);
    }
}

10. 199. 二叉树的右视图

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例:

输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:

   1            <---
 /   \
2     3         <---
 \     \
  5     4       <---

基本思路: 先序遍历, 记录每一层深度下的节点的值, 并先记录左节点再记录右节点, 则最后记录的值即为该层深度的右视图看到的值

class Solution {
    
    
    public List<Integer> rightSideView(TreeNode root) {
    
    
        List<List<Integer>> allList = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        if (root == null) return list;
        dfs(root, 0, allList);

        for (int i = 0; i < allList.size(); i++) {
    
    
            list.add(allList.get(i).get(allList.get(i).size() - 1));
        }

        return list;
    }

    private void dfs(TreeNode root, int level, List<List<Integer>> allList) {
    
    
        if (root == null) return;
        if (level == allList.size()) allList.add(new ArrayList<Integer>());
        allList.get(level).add(root.val);
        dfs(root.left, level + 1, allList);
        dfs(root.right, level + 1, allList);
    }
}

11. 104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7]3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

class Solution {
    
    
    public int maxDepth(TreeNode root) {
    
    
        return root == null ? 0 : 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
    }
}

12. 107. 二叉树的层序遍历 II

给定一个二叉树,返回其节点值自底向上的层序遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如:
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其自底向上的层序遍历为:

[
  [15,7],
  [9,20],
  [3]
]
class Solution {
    
    
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
    
    
        List<List<Integer>> reverse = new ArrayList<>();
        dfs(root, 0, reverse);
        List<List<Integer>> result = new ArrayList<>();
        for (List<Integer> list: reverse) {
    
    
            result.add(0, list);
        }

        return result;
    }

    private void dfs(TreeNode root, int level, List<List<Integer>> result) {
    
    
        if (root == null) return;
        if (result.size() == level) result.add(new ArrayList<Integer>());
        result.get(level).add(root.val);
        dfs(root.left, level + 1, result);
        dfs(root.right, level + 1, result);
    }
}

参考

https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal/solution/yi-tao-quan-fa-shua-diao-nge-bian-li-shu-de-wen–3/

猜你喜欢

转载自blog.csdn.net/zgpeace/article/details/115387573