1.树的遍历

广度优先遍历

  1. public int bfs(TreeNode root) {
  2. if (root == null) {
  3. return 0;
  4. }
  5. Deque<TreeNode> queue = new ArrayDeque<>();
  6. queue.offer(root);
  7. int ans = 0;
  8. while (!queue.isEmpty()) {
  9. int size = queue.size();
  10. while (size > 0) {
  11. TreeNode node = queue.poll();
  12. if (node.left != null) {
  13. queue.offer(node.left);
  14. }
  15. if (node.right != null) {
  16. queue.offer(node.right);
  17. }
  18. size--;
  19. }
  20. ans++;
  21. }
  22. return ans;
  23. }

深度优先遍历

  1. public static void dfs(Node treeNode) {
  2. if (treeNode == null) {
  3. return;
  4. }
  5. // 遍历节点
  6. process(treeNode)
  7. // 遍历左节点
  8. dfs(treeNode.left);
  9. // 遍历右节点
  10. dfs(treeNode.right);
  11. }
  12. public static void dfsWithStack(Node root) {
  13. if (root == null) {
  14. return;
  15. }
  16. Stack<Node> stack = new Stack<>();
  17. // 先把根节点压栈
  18. stack.push(root);
  19. while (!stack.isEmpty()) {
  20. Node treeNode = stack.pop();
  21. // 遍历节点
  22. process(treeNode)
  23. // 先压右节点
  24. if (treeNode.right != null) {
  25. stack.push(treeNode.right);
  26. }
  27. // 再压左节点
  28. if (treeNode.left != null) {
  29. stack.push(treeNode.left);
  30. }
  31. }
  32. }

翻转二叉树

  • 只要把二叉树上的每一个节点的左右子节点进行交换,最后的结果就是完全翻转之后的二叉树

    // 将整棵树的节点翻转
    TreeNode invertTree(TreeNode root) {
      // base case
      if (root == null) {
          return null;
      }
    
      /**** 前序遍历位置 ****/
      // root 节点需要交换它的左右子节点
      TreeNode tmp = root.left;
      root.left = root.right;
      root.right = tmp;
    
      // 让左右子节点继续翻转它们的子节点
      invertTree(root.left);
      invertTree(root.right);
    
      return root;
    }
    

    根据前序,中序,后序 生成树

根据后序和中序生成二叉树,核心思想是通过前序/后序找到根,再根据中序的根左右生成左右子树
image.png

TreeNode build(int[] inorder, int inStart, int inEnd,
               int[] postorder, int postStart, int postEnd) {

    if (inStart > inEnd) {
        return null;
    }
    // root 节点对应的值就是后序遍历数组的最后一个元素
    int rootVal = postorder[postEnd];
    // rootVal 在中序遍历数组中的索引
    int index = 0;
    for (int i = inStart; i <= inEnd; i++) {
        if (inorder[i] == rootVal) {
            index = i;
            break;
        }
    }
    // 左子树的节点个数
    int leftSize = index - inStart;
    TreeNode root = new TreeNode(rootVal);
    // 递归构造左右子树
    root.left = build(inorder, inStart, index - 1,
                        postorder, postStart, postStart + leftSize - 1);

    root.right = build(inorder, index + 1, inEnd,
                        postorder, postStart + leftSize, postEnd - 1);
    return root;
}

二维数组dfs

image.png

记忆化dfs

public class longestIncreasingPath {
    /**
     * dirs用于移动当前数字
     */
    private static int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
    private static int m, n;

    public static void main(String[] args) {
        int[][] param = {{9, 9, 4}, {6, 6, 8}, {2, 1, 1}};
        longestIncreasingPath(param);
    }

    public static int longestIncreasingPath(int[][] matrix) {
        m = matrix.length;
        n = matrix[0].length;
        int[][] dp = new int[m][n];
        int res = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                res = Math.max(res, dfs(matrix, i, j, dp));
            }
        }
        return res;
    }

    public static int dfs(int[][] matrix, int i, int j, int[][] dp) {
        if (dp[i][j] != 0) return dp[i][j];
        for (int[] dir : dirs) {
            int row = i + dir[0];
            int col = j + dir[1];
            if (row >= 0 && row < m && col >= 0 && col < n && matrix[i][j] < matrix[row][col]){
                dp[i][j] = Math.max(dp[i][j],dfs(matrix,row,col,dp)+1);
            }
        }
        return dp[i][j];
    }
}