有关树的算法题小结

有关树的算法题小结

:happy: 一点点小总结,后续继续补充

富察·容音 当题中提到有关树的结构时,可以从以下几个方向考虑:递归(居多)、栈、队列。比如以下几题:

递归

对于二叉树,其结构较为固定,很容易想到把一棵树的问题分解为左右子树的问题,这样可以尝试使用下递归的思路。在递归的同时,记录下变量的值(例如节点、深度),可以解决某些问题(例如:题目1 题目2)。这里可以注意递归的方式,是左中右、右中左题目3。对于搜索二叉树中两种遍历方式可以解决不同问题,例如使用右中左的方式则可以获取较大值,例如 题目

题目0: 求二叉树中序遍历结果

public class BinaryTreeInorderTraversal {
    /**
     * 二叉树中序排序,递归
     * @param root 根节点
     * @param list 记录
     */
    private void solution(TreeNode root, List<Integer> list) {
        if (root.left != null) {
            solution(root.left, list);
        }
        if (root != null) {
            list.add(root.val);
        }
        if (root.right != null) {
            solution(root.right, list);
        }
    }
​
​
    /**
     * 二叉树中序排序,非递归
     *
     * @param root 根节点
     *             思路:
     *             *1:遍历左子树入栈*
     *             *2:pop出一个,取出值*
     *             *3:对右子树继续操作*
     *             *4:重复3-4*
     */
    private List<Integer> solution(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
​
        pushAllLeft(root, stack);
​
        while (!stack.empty()) {
            TreeNode node = stack.pop();
            list.add(node.val);
            pushAllLeft(node.right, stack);
        }
        return list;
    }
    private void pushAllLeft(TreeNode root, Stack<TreeNode> stack) {
        while (null != root) {
            stack.push(root);
            root = root.left;
        }
    }
}

 

题目1: 求取根到叶子节点的路径

/**
 * https://leetcode.com/problems/binary-tree-paths/description/
 */
public class BinaryTreePaths {
    List<String> resultList = new ArrayList<String>();
​
    /**
     * 递归 找到跟到叶子节点路径输出。这里直接记录递归过程中节点的值。
     * @param root
     * @return 路径输出
     */
    public List<String> solution(TreeNode root) {
        if (root == null) {
            return resultList;
        }
        findPaths(root, root.val + "");
        return resultList;
    }
    private void findPaths(TreeNode node, String path) {
        if (node.left == null && node.right == null) {
            resultList.add(path);
        }
        if (node.left != null) {
            findPaths(node.left, path + "->" + node.left.val);
        }
        if (node.right != null) {
            findPaths(node.right, path + "->" + node.right.val);
        }
    }
}
​

题目2:巧用递归1:倒序按行输出节点的值

/**
 * 倒序按行输出节点的值
 * 例如:
 * Given binary tree [3,9,20,null,null,15,7],
 * 3
 * / \
 * 9  20
 * /  \
 * 15   7
 * return its bottom-up level order traversal as:
 * [
 * [15,7],
 * [9,20],
 * [3]
 * ]
 * <p/>
 * https://leetcode.com/problems/binary-tree-level-order-traversal-ii/description
 */
public class BinaryTreeLevelOrderTraversal {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> list = new LinkedList<List<Integer>>();
​
        levleMaker(list, root, 0);
        return list;
    }
​
    /**
     * 倒序 按行输出节点值,这里采用了递归的方式,在递归的过程中使用深度控制节点的位置
     * @param list  返回值
     * @param root  根节点
     * @param level 深度
     *              思路:在遍历的时候,根据深度new、并插入list
     */
    private void levleMaker(List<List<Integer>> list, TreeNode root, int level) {
        if (root == null) return;
        if (list.size() <= level) {
            list.add(new LinkedList<Integer>());
        }
        levleMaker(list, root.left, level + 1);
        levleMaker(list, root.right, level + 1);
        list.get(list.size() - 1 - level).add(root.val);
    }
}

题目3:巧用递归2 :搜索二叉树,每个节点加上比他大的节点

  Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST  is changed to the original key plus sum of all keys greater than the original key in BST.
  Example:
  Input: The root of a Binary Search Tree like this:
  5
  /   \
  2     13
  Output: The root of a Greater Tree like this:
  18
  /   \
  20     13
 https://leetcode.com/problems/convert-bst-to-greater-tree/description/
​
public class ConvertBSTtoGreaterTree {
    int sum = 0;
​
    /**
     * 搜索二叉树,每个节点加上比他大的节点
     *
     * @param root 根节点
     * @return 根节点
     * 思路:
     * 1:递归从大到小遍历,右中(记录和)左
     * (我们可以做一个正序遍历来遍历树的节点。在这个过程中,我们跟踪到目前为止我们已经遍历的所有节点的运行总和。)
     */
    public TreeNode convertBST(TreeNode root) {
        if (root == null)
            return null;
        convertBST(root.right);
​
        root.val += sum;
        sum = root.val;
​
        convertBST(root.left);
        return root;
    }
}

队列

题目4:倒序按行输出节点的值。同题目2,但此时使用队列的方式

  /**
     * 广度优先遍历算法
     * @param root
     * @return
     */
    public List<List<Integer>> levelOrderBottom2(TreeNode root) {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        if (root == null) return list;
​
        Queue<TreeNode> queue = new ArrayDeque<TreeNode>();
        queue.add(root);
​
        while (!queue.isEmpty()) {
            int levelNum = queue.size();
            List<Integer> subList = new LinkedList<Integer>();
            for (int i = 0; i < levelNum; i++) {
                if (queue.peek().left != null) queue.offer(queue.peek().left);
                if (queue.peek().right != null) queue.offer(queue.peek().right);
                subList.add(queue.poll().val);
            }
            list.add(0, subList);
        }
        return list;
​
    }

题目5: 编写迭代器,返回二叉搜索树中最小的值

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章