• Chapter three Binary Tree & Divide Conquer(二叉树&分治)


    1.binary-tree-preorder-traversal(二叉树的前序遍历)根-左-右

    给出一棵二叉树,返回其节点值的前序遍历。

    非递归解法【要记住】:

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: Preorder in ArrayList which contains node values.
         */
        public ArrayList<Integer> preorderTraversal(TreeNode root) {
            // write your code here
            Stack<TreeNode> stack = new Stack<TreeNode>();
            ArrayList<Integer> preorder = new ArrayList<Integer>();
            if (root == null) {
                return preorder;
            }
            stack.push(root);
            while (!stack.empty()) {
                TreeNode node = stack.pop();
                preorder.add(node.val);
                if (node.right != null) {
                    stack.push(node.right);
                }
                if (node.left != null) {
                    stack.push(node.left);
                }
            }
            return preorder;
        }
    }
    View Code

    由于stack的先进后出特性要注意先push node.right 后push node.left。

    递归解法:

    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: Preorder in ArrayList which contains node values.
         */
        public ArrayList<Integer> preorderTraversal(TreeNode root) {
            // write your code here
            ArrayList<Integer> preorder = new ArrayList<Integer>();
            traverse(root, preorder);
            return preorder;
        }
        private void traverse(TreeNode root, ArrayList<Integer> preorder) {
            if (root == null) {
                return;
            }
            preorder.add(root.val);
            traverse(root.left, preorder);
            traverse(root.right, preorder);
        }
    }
    View Code

    分治解法:

    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: Preorder in ArrayList which contains node values.
         */
        public ArrayList<Integer> preorderTraversal(TreeNode root) {
            // write your code here
            ArrayList<Integer> preorder = new ArrayList<Integer>();
            if (root == null) {
                return preorder;
            }
            ArrayList<Integer> left = preorderTraversal(root.left);
            ArrayList<Integer> right = preorderTraversal(root.right);
            preorder.add(root.val);
            preorder.addAll(left);
            preorder.addAll(right);
            return preorder;
        }
    }
    View Code

    add()和addAll()的区别和使用

    2.binary-tree-inorder-traversal(二叉树的中序遍历)左-根-右

    给出一棵二叉树,返回其中序遍历。

    非递归解法【要记住】:

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: Inorder in ArrayList which contains node values.
         */
        public ArrayList<Integer> inorderTraversal(TreeNode root) {
            // write your code here
            Stack<TreeNode> stack = new Stack<TreeNode>();
            ArrayList<Integer> inorder= new ArrayList<Integer>();
            TreeNode curt = root;
            while (curt != null || !stack.empty()) {
                while (curt != null) {
                    stack.push(curt);
                    curt = curt.left;
                }
                curt = stack.pop();
                inorder.add(curt.val);
                curt = curt.right;
            }
            return inorder;
        }
    }
    View Code

    curt的使用。

    分治:

    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: Inorder in ArrayList which contains node values.
         */
        public ArrayList<Integer> inorderTraversal(TreeNode root) {
            // write your code here
            ArrayList<Integer> inorder = new ArrayList<Integer>();
            if (root == null) {
                return inorder;
            }
            ArrayList<Integer> left = inorderTraversal(root.left);
            ArrayList<Integer> right = inorderTraversal(root.right);
            inorder.addAll(left);
            inorder.add(root.val);
            inorder.addAll(right);
            return inorder;
        }
    }
    View Code

    3.binary-tree-postorder-traversal(二叉树的后序遍历)左- 右- 根

    给出一棵二叉树,返回其节点值的后序遍历。

    迭代解法【要记住】:

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: Postorder in ArrayList which contains node values.
         */
        public ArrayList<Integer> postorderTraversal(TreeNode root) {
            // write your code here
            Stack<TreeNode> stack = new Stack<TreeNode>();
            ArrayList<Integer> postorder = new ArrayList<Integer>();
            TreeNode prev = null;
            TreeNode curt = root;
            if (root == null) {
                return postorder;
            }
            stack.push(root);
            while (!stack.empty()) {
                curt = stack.peek();
                if (prev == null || prev.left == curt || prev.right == curt) {
                    if (curt.left != null) {
                        stack.push(curt.left);
                    } else if (curt.right != null) {
                        stack.push(curt.right);
                    }
                } else if (curt.left == prev) {
                    if (curt.right != null) {
                        stack.push(curt.right);
                    }
                } else {
                    postorder.add(curt.val);
                    stack.pop();
                }
                prev = curt;
            }
            return postorder;
        }
    }
    View Code

    curt和prev的使用。分三种情况讨论:沿着树向下遍历、从左向上遍历树和其他。

    分治解法:

    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: Postorder in ArrayList which contains node values.
         */
        public ArrayList<Integer> postorderTraversal(TreeNode root) {
            // write your code here
            ArrayList<Integer> postorder = new ArrayList<Integer>();
            if (root == null) {
                return postorder;
            }
            ArrayList<Integer> left = postorderTraversal(root.left);
            ArrayList<Integer> right = postorderTraversal(root.right);
            postorder.addAll(left);
            postorder.addAll(right);
            postorder.add(root.val);
            return postorder;
        }
    }
    View Code

    4.maximum-depth-of-binary-tree(二叉树的最大深度)

    给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的距离。

    分治解法:

    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: An integer.
         */
        public int maxDepth(TreeNode root) {
            // write your code here
            if (root == null) {
                return 0;
            }
            int left = maxDepth(root.left);
            int right = maxDepth(root.right);
            return Math.max(left, right) + 1;
        }
    }
    View Code

    遍历解法:

    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: An integer.
         */
        private int depth = Integer.MIN_VALUE;
        public int maxDepth(TreeNode root) {
            // write your code here
            if (root == null) {
                return 0;
            }
            helper(root, 1);
            return depth;
        }
        private void helper(TreeNode root, int curtDepth) {
            if (root == null) {
                return;
            }
            if (curtDepth > depth) {
                depth = curtDepth;
            }
            helper(root.left, curtDepth + 1);
            helper(root.right, curtDepth + 1);
        }
    }
    View Code

    遍历解法一般都会有helper()函数帮助,需要全局变量depth记录最大深度。

    5.minimum-depth-of-binary-tree(二叉树的最小深度)

    给定一个二叉树,找出其最小深度。二叉树的最小深度为根节点到最近叶子节点的距离。

    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: An integer.
         */
        public int minDepth(TreeNode root) {
            // write your code here
            if (root == null) {
                return 0;
            }
            return getMin(root);
        }
        private int getMin(TreeNode root) {
            if (root == null) {
                return Integer.MAX_VALUE;
            }
            int left = getMin(root.left);
            int right = getMin(root.right);
            if (root.left == null && root.right == null) {
                return 1;
            }
            return Math.min(left, right) + 1;
        }
    }
    View Code

    注意:getMin()函数中,if(root == null){return Integer.MAX_VALUE;} 遇到叶子结点结束,if(root.left == null && root.right == null){return 1;}

    6.binary-tree-paths(二叉树的所有路径)

    给一棵二叉树,找出从根节点到叶子节点的所有路径。

    分治解法:

    public class Solution {
        /**
         * @param root the root of the binary tree
         * @return all root-to-leaf paths
         */
        public List<String> binaryTreePaths(TreeNode root) {
            // Write your code here
            List<String> results = new ArrayList<String>();
            if (root == null) {
                return results;
            }
            List<String> leftResults = binaryTreePaths(root.left);
            List<String> rightResults = binaryTreePaths(root.right);
            for (String result : leftResults) {
                results.add(root.val + "->" + result);
            }
            for (String result : rightResults) {
                results.add(root.val + "->" + result);
            }
            if (results.size() == 0) {
                results.add("" + root.val);
            }
            return results;
        }
    }
    View Code

    遍历解法:

    public class Solution {
        /**
         * @param root the root of the binary tree
         * @return all root-to-leaf paths
         */
        public List<String> binaryTreePaths(TreeNode root) {
            // Write your code here
            List<String> paths = new ArrayList<String>();
            if (root == null) {
                return paths;
            }
            helper(root, String.valueOf(root.val), paths);
            return paths;
        }
        private void helper(TreeNode root, String path, List<String> paths) {
            if (root == null) {
                return;
            }
            if (root.left == null && root.right == null) {
                paths.add(path);
                return;
            }
            if (root.left != null) {
                helper(root.left, path + "->" + String.valueOf(root.left.val), paths);
            }
            if (root.right != null) {
                helper(root.right, path + "->" + String.valueOf(root.right.val), paths);
            }
        }
    }
    View Code

    注意:private void helper(TreeNode root, String path, List<String> paths) {}

    7.minimum-subtree(最小和子树)

    给定一个二叉树,找到具有最小和的子树。 返回子树的根。保证只有一个具有最小和的子树,给定的二叉树不是空树。

    分治+遍历解法:

    public class Solution {
        private TreeNode subtree = null;
        private int subtreeSum = Integer.MAX_VALUE;
        /**
         * @param root the root of binary tree
         * @return the root of the minimum subtree
         */
        public TreeNode findSubtree(TreeNode root) {
            // Write your code here
            helper(root);
            return subtree;
        }
        private int helper(TreeNode root) {
            if (root == null) {
                return 0;
            }
            int sum = helper(root.left) + helper(root.right) + root.val;
            if (sum < subtreeSum) {
                subtreeSum = sum;
                subtree = root;
            }
            return sum;
        }
    }
    View Code

    注意:全局变量TreeNode subtree和int subtreeSum进行记录。

    纯分治解法:

    class ResultType {
        public TreeNode subtree;
        public int sum;
        public int minSum;
        public ResultType(TreeNode subtree, int sum, int minSum) {
            this.subtree = subtree;
            this.sum = sum;
            this.minSum = minSum;
        }
    }
    public class Solution {
        /**
         * @param root the root of binary tree
         * @return the root of the minimum subtree
         */
        public TreeNode findSubtree(TreeNode root) {
            // Write your code here
            ResultType result = helper(root);
            return result.subtree;
        }
        private ResultType helper(TreeNode root) {
            if (root == null) {
                return new ResultType(null, 0, Integer.MAX_VALUE);
            }
            ResultType leftResult = helper(root.left);
            ResultType rightResult = helper(root.right);
            ResultType result = new ResultType(
                root,
                leftResult.sum + rightResult.sum + root.val,
                leftResult.sum + rightResult.sum + root.val);
            if (leftResult.minSum < result.minSum) {
                result.minSum = leftResult.minSum;
                result.subtree = leftResult.subtree;
            }
            if (rightResult.minSum < result.minSum) {
                result.minSum = rightResult.minSum;
                result.subtree = rightResult.subtree;
            }
            return result;
        }
    }
    View Code

    注意:class ResultType{int var1,var2;}的使用。在求最大/最小值时,赋初值Integer.MIN_VALUE/Integer.MAX_VALUE。

    8.balanced-binary-tree(平衡二叉树)

    给定一个二叉树,确定它是高度平衡的。对于这个问题,一棵高度平衡的二叉树的定义是:一棵二叉树中每个节点的两个子树的深度相差不会超过1。 

    不使用ResultType的解法:

    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: True if this Binary tree is Balanced, or false.
         */
        public boolean isBalanced(TreeNode root) {
            // write your code here
            return maxDepth(root) != -1;
        }
        private int maxDepth(TreeNode root) {
            if (root == null) {
                return 0;
            }
            int left = maxDepth(root.left);
            int right = maxDepth(root.right);
            if (left == -1 || right == -1 || Math.abs(left - right) > 1) {
                return -1;
            }
            return Math.max(left, right) + 1;
        }
    }
    View Code

    使用ResultType的解法:

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    class ResultType {
        public boolean isBalanced;
        public int maxDepth;
        public ResultType(boolean isBalanced, int maxDepth) {
            this.isBalanced = isBalanced;
            this.maxDepth = maxDepth;
        }
    }
    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: True if this Binary tree is Balanced, or false.
         */
        public boolean isBalanced(TreeNode root) {
            return helper(root).isBalanced;
        }
        private ResultType helper(TreeNode root) {
            if (root == null) {
                return new ResultType(true, 0);
            }
            ResultType left = helper(root.left);
            ResultType right = helper(root.right);
            // subtree not balance, root not balance
            if (!left.isBalanced || !right.isBalanced || Math.abs(left.maxDepth - right.maxDepth) > 1) {
                return new ResultType(false, -1);
            }
            return new ResultType(true, Math.max(left.maxDepth, right.maxDepth) + 1);
        }
    }
    View Code

    注意:class ResultType {public boolean isBalanced; public int maxDepth}记录是否为平衡二叉树和树的最大深度。

    9.subtree-with-maximum-average(具有最大平均值的子树)

    给定一个二叉树,找到最大平均值的子树。 返回子树的根。

    使用ResultType,分治+遍历的解法:

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    class ResultType{
        public int sum;
        public int size;
        public ResultType(int sum, int size) {
            this.sum = sum;
            this.size = size;
        }
    }
    public class Solution {
        /**
         * @param root the root of binary tree
         * @return the root of the maximum average of subtree
         */
        private TreeNode subtree = null;
        private ResultType subtreeResult = null;
        public TreeNode findSubtree2(TreeNode root) {
            // Write your code here
            helper(root);
            return subtree;
        }
        private ResultType helper(TreeNode root) {
            if (root == null) {
                return new ResultType(0, 0);
            }
            ResultType left = helper(root.left);
            ResultType right = helper(root.right);
            ResultType result = new ResultType(
                left.sum + right.sum + root.val,
                left.size + right.size + 1
            );
            if (subtree == null ||
                subtreeResult.sum * result.size < result.sum * subtreeResult.size
            ) {
                subtree = root;
                subtreeResult = result;
            }
            return result;
        }
    }
    View Code

    10.flatten-binary-tree-to-linked-list(将二叉树拆成链表)

    将一棵二叉树按照前序遍历拆解成为一个假链表。所谓的假链表是说,用二叉树的 right 指针,来表示链表中的 next 指针。不要忘记将左儿子标记为 null,否则你可能会得到空间溢出或是时间溢出。

    遍历解法:

    public class Solution {
        /**
         * @param root: a TreeNode, the root of the binary tree
         * @return: nothing
         */
        private TreeNode lastNode = null;
        public void flatten(TreeNode root) {
            // write your code here
            if (root == null) {
                return;
            }
            if (lastNode != null) {
                lastNode.left = null;
                lastNode.right = root;
            }
            lastNode = root;
            TreeNode right = root.right;
            flatten(root.left);
            flatten(right);
        }
    }
    View Code

    注意:定义lastNode记录上一个被访问的节点。当lastNode不为空时,将lastNode的左儿子置空,右儿子置当前root。根据题目要求的前序遍历方法,要保存当前root的右子树,然后先拆解左子树,再拆解右子树。

    非递归解法:

    public class Solution {
        /**
         * @param root: a TreeNode, the root of the binary tree
         * @return: nothing
         */
        public void flatten(TreeNode root) {
            // write your code here
            Stack<TreeNode> stack = new Stack<TreeNode>();
            if (root == null) {
                return;
            }
            stack.push(root);
            while (!stack.empty()) {
                TreeNode node = stack.pop();
                if (node.right != null) {
                    stack.push(node.right);
                }
                if (node.left != null) {
                    stack.push(node.left);
                }
                //connect
                node.left = null;
                if (stack.empty()) {
                    node.right = null;
                } else {
                    node.right = stack.peek();
                }
            }
        }
    }
    View Code

    注意:在非递归前序遍历的基础上添加connect:当前node=stack.pop()的左儿子置空,右儿子置stack.peek()。

    LCA最近公共祖先

    11.lowest-common-ancestor(最近公共祖先)【高频题】

    给定一棵二叉树,找到两个节点的最近公共父节点(LCA)。最近公共祖先是两个节点的公共的祖先节点且具有最大深度。假设给出的两个节点都在树中存在。

    分治解法:

    public class Solution {
        /**
         * @param root: The root of the binary search tree.
         * @param A and B: two nodes in a Binary.
         * @return: Return the least common ancestor(LCA) of the two nodes.
         */
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
            // write your code here
            if (root == null || root == A || root == B) {
                return root;
            }
            TreeNode left = lowestCommonAncestor(root.left, A, B);
            TreeNode right = lowestCommonAncestor(root.right, A, B);
            if (left != null && right != null) {
                return root;
            }
            if (left != null) {
                return left;
            }
            if (right != null){
                return right;
            }
            return null;
        }
    }
    View Code

    注意:在root为根的二叉树中找A,B的LCA;如果找到了就返回这个LCA,如果只碰到A,就返回A;如果只碰到B,就返回B;如果都没有,就返回null。

    12.lowest-common-ancestor-ii(最近公共祖先II)

    给一棵二叉树和二叉树中的两个节点,找到这两个节点的最近公共祖先LCA。两个节点的最近公共祖先,是指两个节点的所有父亲节点中(包括这两个节点),离这两个节点最近的公共的节点。每个节点除了左右儿子指针以外,还包含一个父亲指针parent,指向自己的父亲。

    跟第10题同样的方法也可解:

    /**
     * Definition of ParentTreeNode:
     * 
     * class ParentTreeNode {
     *     public ParentTreeNode parent, left, right;
     * }
     */
    public class Solution {
        /**
         * @param root: The root of the tree
         * @param A, B: Two node in the tree
         * @return: The lowest common ancestor of A and B
         */
        public ParentTreeNode lowestCommonAncestorII(ParentTreeNode root,
                                                     ParentTreeNode A,
                                                     ParentTreeNode B) {
            // Write your code here
            if (root == null || root == A || root == B) {
                return root;
            }
            ParentTreeNode left = lowestCommonAncestorII(root.left, A, B);
            ParentTreeNode right = lowestCommonAncestorII(root.right, A, B);
            if (left != null && right != null) {
                return root;
            }
            if (left != null) {
                return left;
            }
            if (right != null){
                return right;
            }
            return null;
        }
    }
    View Code

    或者:

    /**
     * Definition of ParentTreeNode:
     * 
     * class ParentTreeNode {
     *     public ParentTreeNode parent, left, right;
     * }
     */
    public class Solution {
        /**
         * @param root: The root of the tree
         * @param A, B: Two node in the tree
         * @return: The lowest common ancestor of A and B
         */
        public ParentTreeNode lowestCommonAncestorII(ParentTreeNode root,
                                                     ParentTreeNode A,
                                                     ParentTreeNode B) {
            // Write your code here
            ArrayList<ParentTreeNode> pathA = getPath(A);
            ArrayList<ParentTreeNode> pathB = getPath(B);
            int sizeA = pathA.size() - 1;
            int sizeB = pathB.size() - 1;
            ParentTreeNode lowestAncestor = null;
            while (sizeA >= 0 && sizeB >= 0) {
                if (pathA.get(sizeA) != pathB.get(sizeB)) {
                    break;
                }
                lowestAncestor = pathA.get(sizeA);
                sizeA--;
                sizeB--;
            }
            return lowestAncestor;
        }
        private ArrayList<ParentTreeNode> getPath(ParentTreeNode node) {
            ArrayList<ParentTreeNode> path = new ArrayList<ParentTreeNode>();
            while (node != null) {
                path.add(node);
                node = node.parent;
            }
            return path;
        }
    }
    View Code

    注意:利用parent指针自底向上记录A,B的路径,自顶向下找最后一个相同的节点即为要求的点。

    13.lowest-common-ancestor-iii(最近公共祖先III)

    给一棵二叉树和二叉树中的两个节点,找到这两个节点的最近公共祖先LCA。两个节点的最近公共祖先,是指两个节点的所有父亲节点中(包括这两个节点),离这两个节点最近的公共的节点。返回 null 如果两个节点在这棵树上不存在最近公共祖先的话。这两个节点未必都在这棵树上出现。

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    class ResultType{
        public boolean a_exist;
        public boolean b_exist;
        public TreeNode node;
        public ResultType(boolean a, boolean b, TreeNode node) {
            this.a_exist = a;
            this.b_exist = b;
            this.node = node;
        }
    }
    public class Solution {
        /**
         * @param root The root of the binary tree.
         * @param A and B two nodes
         * @return: Return the LCA of the two nodes.
         */
        public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) {
            // write your code here
            ResultType result = helper(root, A, B);
            if (result.a_exist && result.b_exist) {
                return result.node;
            } else {
                return null;
            }
        }
        private ResultType helper(TreeNode root, TreeNode A, TreeNode B) {
            if (root == null) {
                return new ResultType(false, false, null);
            }
            ResultType leftResult = helper(root.left, A, B);
            ResultType rightResult = helper(root.right, A, B);
            boolean a_exist = leftResult.a_exist || rightResult.a_exist || root == A;
            boolean b_exist = leftResult.b_exist || rightResult.b_exist || root == B;
            if (root == A || root == B) {
                return new ResultType(a_exist, b_exist, root);
            }
            if (leftResult.node != null && rightResult.node != null) {
                return new ResultType(a_exist, b_exist, root);
            }
            if (leftResult.node != null) {
                return new ResultType(a_exist, b_exist, leftResult.node);
            }
            if (rightResult.node != null) {
                return new ResultType(a_exist, b_exist, rightResult.node);
            }
            return new ResultType(a_exist, b_exist, null);
        }
    }
    View Code

    注意:使用ResultType{boolean a_exist,b_exist;TreeNode node}判断A和B节点是否都存在;然后在以root为根的二叉树中找A,B的LCA;如果找到了就返回这个LCA,如果只碰到A,就返回A;如果只碰到B,就返回B;如果都没有,就返回null。

    LCS最长连续序列

    14.binary-tree-longest-consecutive-sequence(最长连续序列)

    给定二叉树,找到最长连续序列路径的长度并返回。该路径是指从某个起始节点到父子连接树中节点的任意节点序列。 最长的连续路径需要从父母到孩子(不能相反)。

    分治+遍历解法:

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
        /**
         * @param root the root of binary tree
         * @return the length of the longest consecutive sequence path
         */
        private int longest = Integer.MIN_VALUE;
        public int longestConsecutive(TreeNode root) {
            // Write your code here
            helper(root);
            return longest;
        }
        private int helper(TreeNode root) {
            if (root == null) {
                return 0;
            }
            int left = helper(root.left);
            int right = helper(root.right);
            int subtreeLongest = 1;
            if (root.left != null && root.val + 1 == root.left.val) {
                subtreeLongest = Math.max(subtreeLongest, left + 1);
            }
            if (root.right != null && root.val + 1 == root.right.val) {
                subtreeLongest = Math.max(subtreeLongest, right + 1);
            }
            if (subtreeLongest > longest) {
                longest = subtreeLongest;
            }
            return subtreeLongest;
        }
    }
    View Code

    使用全局变量longest存储最大长度。如果是连续序列,则root.val + 1 == root.left(right).val。

    15.binary-tree-longest-consecutive-sequence-ii(最长连续序列II)

    给定二叉树,找到最长连续序列路径的长度并返回。该路径可以在树中的任何节点处开始和结束。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class ResultType {
        public int max_length;
        public int max_down;
        public int max_up;
        public ResultType(int length, int down, int up) {
            this.max_length = length;
            this.max_down = down;
            this.max_up = up;
        }
    }
    public class Solution {
        /**
         * @param root the root of binary tree
         * @return the length of the longest consecutive sequence path
         */
        public int longestConsecutive2(TreeNode root) {
            // Write your code here
            return helper(root).max_length;
        }
        private ResultType helper(TreeNode root) {
            if (root == null) {
                return new ResultType(0, 0, 0);
            }
            ResultType left = helper(root.left);
            ResultType right = helper(root.right);
            int down = 0;
            int up = 0;
            if (root.left != null && root.left.val + 1 == root.val) {
                down = Math.max(down, left.max_down + 1);
            }
            if (root.left != null && root.left.val - 1 == root.val) {
                up = Math.max(up, left.max_up + 1);
            }
            if (root.right != null && root.right.val + 1 == root.val) {
                down = Math.max(down, right.max_down + 1);
            }
            if (root.right != null && root.right.val - 1 == root.val) {
                up = Math.max(up, right.max_up + 1);
            }
            int len = down + 1 + up;
            len = Math.max(len, Math.max(left.max_length, right.max_length));
            return new ResultType(len, down, up);
        }
    }
    View Code

    注意:这个问题中拐点很重要。上升和下降序列和拐点拼在一起才是完整的序列。使用ResultType{int max_length,max_down,max_up}储存结果。

    len = Math.max(len, Math.max(left.max_length, right.max_length));先求左右子树中的最大长度,然后最终的最大长度。

    16.binary-tree-longest-consecutive-sequence-iii(最长连续序列III)

    最长连续序列II的后续问题。给定一个k-ary树,找到最长连续序列路径的长度并返回。该路径可以在树中的任何节点处开始和结束。

    /**
     * Definition for a multi tree node.
     * public class MultiTreeNode {
     *     int val;
     *     List<TreeNode> children;
     *     MultiTreeNode(int x) { v(al = x; }
     * }
     */
    class ResultType {
        public int max_len;
        public int max_down;
        public int max_up;
        public ResultType(int length, int down, int up) {
            this.max_len = length;
            this.max_down = down;
            this.max_up = up;
        }
    }
    public class Solution {
        /**
         * @param root the root of k-ary tree
         * @return the length of the longest consecutive sequence path
         */
        public int longestConsecutive3(MultiTreeNode root) {
            // Write your code here
            return helper(root).max_len;
        }
        private ResultType helper(MultiTreeNode root) {
            if (root == null) {
                return new ResultType(0, 0, 0);
            }
            int down = 0;
            int up = 0;
            int max_len = 1;
            for (MultiTreeNode node : root.children) {
                ResultType result = helper(node);
                if (node.val + 1 == root.val) {
                    down = Math.max(down, result.max_down + 1);
                }
                if (node.val - 1 == root.val) {
                    up = Math.max(up, result.max_up + 1);
                }
                max_len = Math.max(max_len, result.max_len);
            }
            max_len = Math.max(down + 1 + up, max_len);
            return new ResultType(max_len, down, up);
        }
    }
    View Code

    注意:与II思路类似。

    for (MultiTreeNode node : root.children) {
        ResultType result = helper(node);
        .......
        max_len = Math.max(max_len, result.max_len);//chidren节点中的最大长度
    }
    max_len = Math.max(down + 1 + up, max_len);//最终的最大长度

    二叉树的路径和(找出所有路径中各节点相加总和值等于目标值的路径)

    17.binary-tree-path-sum(二叉树的路径和)

    给定一个二叉树,找出所有路径中各节点相加总和等于给定 目标值 的路径。一个有效的路径,指的是从根节点到叶节点的路径。

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root the root of binary tree
         * @param target an integer
         * @return all valid paths
         */
        public List<List<Integer>> binaryTreePathSum(TreeNode root, int target) {
            // Write your code here
            List<List<Integer>> paths = new ArrayList<List<Integer>>();
            if (root == null) {
                return paths;
            }
            ArrayList<Integer> path = new ArrayList<Integer>();
            path.add(root.val);
            helper(root, path, root.val, target, paths);
            return paths;
        }
        private void helper(TreeNode root,
                            ArrayList<Integer> path,
                            int sum,
                            int target,
                            List<List<Integer>> paths) {
            if (root.left == null && root.right == null) {
                if (sum == target) {
                    paths.add(new ArrayList<Integer>(path));
                }
            }
            if (root.left != null) {
                path.add(root.left.val);
                helper(root.left, path, sum + root.left.val, target, paths);
                path.remove(path.size() - 1);
            }
            if (root.right != null) {
                path.add(root.right.val);
                helper(root.right, path, sum + root.right.val, target, paths);
                path.remove(path.size() - 1);
            } 
        }
    }
    View Code

    注意:跟subsets有相似点(遇到叶子结点时若满足条件sum=target就加入results,没遇到叶子结点就继续DFS)。

    private void helper(TreeNode root, ArrayList<Integer> path, int sum, int target, List<List<Integer>> paths)

    18.binary-tree-path-sum-ii(二叉树的路径和II)

    给一棵二叉树和一个目标值,设计一个算法找到二叉树上的和为该目标值的所有路径。路径可以从任何节点出发和结束,但是需要是一条一直往下走的路线。也就是说,路径上的节点的层级是逐个递增的。

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root the root of binary tree
         * @param target an integer
         * @return all valid paths
         */
        public List<List<Integer>> binaryTreePathSum2(TreeNode root, int target) {
            // Write your code here
            List<List<Integer>> paths = new ArrayList<List<Integer>>();
            if (root == null) {
                return paths;
            }
            ArrayList<Integer> buffer = new ArrayList<Integer>();
            helper(root, target, buffer, 0, paths);
            return paths;
        }
        private void helper(TreeNode root,
                           int target,
                           ArrayList<Integer> buffer,
                           int level,
                           List<List<Integer>> paths) {
            if (root == null) {
                return;
            }
            int temp = target;
            buffer.add(root.val);
            for (int i = level; i >= 0; i--) {
                temp -= buffer.get(i);
                if (temp == 0) {
                    ArrayList<Integer> path = new ArrayList<Integer>();
                    for (int j = i; j <= level; j++) {
                        path.add(buffer.get(j));
                    }
                    paths.add(path);
                }
            }
            helper(root.left, target, buffer, level + 1, paths);
            helper(root.right, target, buffer, level + 1, paths);
            buffer.remove(buffer.size() - 1);
        }
    }
    View Code

    注意:一层一层自底向上寻找路径,找到后自顶向下进行添加。

    public void helper(TreeNode root, int sum, ArrayList<Integer> path, int level, List<List<Integer>> paths) {
         int temp = sum;
         ...
         //自底向上寻找路径
         for (int i = level;i >=0; i--)  {
              temp -= path.get(i);
              if (temp == 0) {
                  //自顶向下进行添加
                  for(int j = i; j <= level; j++) {
                      ...
                  }
         }
    }
    View Code

    19.binary-tree-path-sum-iii(二叉树的路径和III)【hard】

    给一棵二叉树和一个目标值,找到二叉树上所有的和为该目标值的路径。路径可以从二叉树的任意节点出发,任意节点结束。

    /**
     * Definition of ParentTreeNode:
     * 
     * class ParentTreeNode {
     *     public int val;
     *     public ParentTreeNode parent, left, right;
     * }
     */
    public class Solution {
        /**
         * @param root the root of binary tree
         * @param target an integer
         * @return all valid paths
         */
        public List<List<Integer>> binaryTreePathSum3(ParentTreeNode root, int target) {
            // Write your code here
            List<List<Integer>> results = new ArrayList<List<Integer>>();
            dfs(root, target, results);
            return results;
        }
        public void dfs(ParentTreeNode root, int target, List<List<Integer>> results) {
            if (root == null) {
                return;
            }
            List<Integer> path = new ArrayList<Integer>();
            findSum(root, null, target, path, results);
            dfs(root.left, target, results);
            dfs(root.right, target, results);
        }
        public void findSum(ParentTreeNode root, ParentTreeNode father, int target,
                     List<Integer> path, List<List<Integer>> results) {
            path.add(root.val);
            target -= root.val;
            if (target == 0) {
                ArrayList<Integer> tmp = new ArrayList<Integer>();
                Collections.addAll(tmp,  new  Integer[path.size()]); 
                Collections.copy(tmp, path); 
                results.add(tmp);
            }
            if (root.parent != null && root.parent != father) {
                findSum(root.parent, root, target, path, results);
            }
            if (root.left != null && root.left  != father) {
                findSum(root.left, root, target, path, results);
            }
            if (root.right != null && root.right != father) {
                findSum(root.right, root, target, path, results);
            }
            path.remove(path.size() - 1);
        }
    }
    View Code

    Binary Search Tree (BST)二叉查找树、二叉搜索树、排序二叉树

    20.validate-binary-search-tree(验证二叉查找树)

    给定一个二叉树,判断它是否是合法的二叉查找树(BST)。一棵BST定义为:节点的左子树中的值要严格小于该节点的值。节点的右子树中的值要严格大于该节点的值。左右子树也必须是二叉查找树。一个节点的树也是二叉查找树。

    分治解法:

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    class ResultType {
        public boolean is_bst;
        public int maxValue;
        public int minValue;
        public ResultType(boolean is_bst, int max, int min) {
            this.is_bst = is_bst;
            this.maxValue = max;
            this.minValue = min;
        }
    }
    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: True if the binary tree is BST, or false
         */
        public boolean isValidBST(TreeNode root) {
            // write your code here
            ResultType r = helper(root);
            return r.is_bst;
        }
        private ResultType helper(TreeNode root) {
            if (root == null) {
                return new ResultType(true, Integer.MIN_VALUE, Integer.MAX_VALUE);
            }
            ResultType left = helper(root.left);
            ResultType right = helper(root.right);
            if (!left.is_bst || !right.is_bst) {
                return new ResultType(false, 0, 0);
            }
            if (root.left != null && left.maxValue >= root.val
                || root.right != null && right.minValue <= root.val) {
                return new ResultType(false, 0, 0);
            }
            return new ResultType(true,
                                  Math.max(root.val, right.maxValue),
                                  Math.min(root.val, left.minValue));
        }
    }
    View Code

    注意:使用class ResultType{boolean is_bst; int maxValue; int minValue;...}存储, 利用left.maxValue<root.val<right.minValue进行判断。

    21.convert-binary-search-tree-to-doubly-linked-list(将二叉查找树转换成双链表)

    将一个二叉查找树按照中序遍历转换成双向链表。

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     * Definition for Doubly-ListNode.
     * public class DoublyListNode {
     *     int val;
     *     DoublyListNode next, prev;
     *     DoublyListNode(int val) {
     *         this.val = val;
     *         this.next = this.prev = null;
     *     }
     * }
     */
    class ResultType {
        DoublyListNode first;
        DoublyListNode last;
        public ResultType(DoublyListNode first, DoublyListNode last) {
            this.first = first;
            this.last = last;
        }
    }
    public class Solution {
        /**
         * @param root: The root of tree
         * @return: the head of doubly list node
         */
        public DoublyListNode bstToDoublyList(TreeNode root) {  
            // Write your code here
            if (root == null) {
                return null;
            }
            ResultType r = helper(root);
            return r.first;
        }
        private ResultType helper(TreeNode root) {
            if (root == null) {
                return null;
            }
            ResultType left = helper(root.left);
            ResultType right = helper(root.right);
            ResultType result = new ResultType(null, null);
            DoublyListNode node = new DoublyListNode(root.val);
            if (left == null) {
                result.first = node;
            } else {
                result.first = left.first;
                left.last.next = node;
                node.prev = left.last;
            }
            if (right == null) {
                result.last = node;
            } else {
                result.last = right.last;
                right.first.prev = node;
                node.next = right.first;
            }
            return result;
        }
    }
    View Code

    注意:使用class ResultType{DoublyListNode first, DoublyListNode last}记录链表的开始节点和结束节点。左右子链表的链接要着重考虑。

    22.inorder-successor-in-binary-search-tree(二叉查找树中序遍历后继)

    给一个二叉查找树,以及一个节点,求该节点的中序遍历后继,如果没有返回null。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    //从root查找p节点的过程,同时保存旧的比p大且相差最小的root节点,作为successor
    public class Solution {
        public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
            TreeNode successor = null;//记录后继节点
            while (root != null && root != p) {
                //如果当前root比p大,继续查找更小的比p大的root
                if (root.val > p.val) {
                    successor = root;//保存比p大且在目前相差最小的root
                    root = root.left;
                } else {
                    root = root.right;//当前root比p小,继续查找更大的比p小的root
                }
            }
            //如果root为空
            if (root == null) {
                return null;
            }
            //此时root与p相等,如果p没有右子树,直接返回当前比p大且相差最小的root
            if (root.right == null) {
                return successor;
            }
            //如果p有右子树,直接找右子树的最小节点(最左下)
            root = root.right;
            while (root.left != null) {
                root = root.left;
            }
            return root;
    
        }
    }
    View Code

    注意:整体思路是从root查找p节点的过程,同时保存旧的比p大且相差最小的root节点,作为successor。使用successor记录后继节点,在root不为空且不等于p的时候,如果当前root比p大,继续查找更小的比p大的root,同时保存比p大且在目前相差最小的root;如果当前root比p小,继续查找更大的比p小的root。循环结束后,如果root为空,直接返回null。此时root与p相等,如果p没有右子树,直接返回当前比p大且相差最小的root,如果p有右子树,直接找右子树的最小节点(最左下),返回即可。

    23. binary-tree-maximum-path-sum(二叉树的最大路径和)

    给出一棵二叉树,寻找一条路径使其路径和最大,路径可以在任一节点中开始和结束(路径和为两个节点之间所在路径上的节点权值之和)。

    分治解法:

    class ResultType {
    // singlePath: 从root往下走到任意点的最大路径,这条路径至少包含一个点
    // maxPath: 从树中任意到任意点的最大路径,这条路径至少包含一个点
        int singlePath;
        int maxPath;
        public ResultType(int singlePath, int maxPath) {
            this.singlePath = singlePath;
            this.maxPath = maxPath;
        }
    }
    public class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: An integer.
         */
        public int maxPathSum(TreeNode root) {
            // write your code here
            ResultType result = helper(root);
            return result.maxPath;
    
        }
        private ResultType helper(TreeNode root) {
            if (root == null) {
                return new ResultType(Integer.MIN_VALUE, Integer.MIN_VALUE);
            }
            // Divide
            ResultType left = helper(root.left);
            ResultType right = helper(root.right);
            // Conquer
            int singlePath =
                Math.max(0, Math.max(left.singlePath, right.singlePath)) + root.val;
            int maxPath = Math.max(left.maxPath, right.maxPath);
            maxPath = Math.max(maxPath,
                               Math.max(left.singlePath, 0) + 
                               Math.max(right.singlePath, 0) + root.val);
            return new ResultType(singlePath, maxPath);
        }
    }
    View Code

    注意:

    class ResultType {
         int singlePath;// singlePath: 从root往下走到任意点的最大路径,这条路径至少包含一个点
         int maxPath;// maxPath: 从树中任意到任意点的最大路径,这条路径至少包含一个点
         ...
    }

    24. binary-tree-maximum-path-sum-ii(二叉树的最大路径和II)

    给一棵二叉树,找出从根节点出发的路径中和最大的一条。这条路径可以在任何二叉树中的节点结束,但是必须包含至少一个点(也就是根了)。

    分治解法: 

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root the root of binary tree.
         * @return an integer
         */
        public int maxPathSum2(TreeNode root) {
            // Write your code here
            if (root == null) {
                return Integer.MIN_VALUE;
            }
            int left = maxPathSum2(root.left);
            int right = maxPathSum2(root.right);
            return root.val + Math.max(0, Math.max(left, right));
        }
    }
    View Code

    注意: return root.val + Math.max(0, Math.max(left,right));这么写是考虑到二叉树的值也可能为负数,负数加上负数和会越来越小,不如不加直接为0。

    25.binary-search-tree-iterator(二叉查找树迭代器)【hard】

    设计实现一个带有下列属性的二叉查找树的迭代器:元素按照递增的顺序被访问(比如中序遍历);next()hasNext()的询问操作要求均摊时间复杂度是O(1)

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     * Example of iterate a tree:
     * BSTIterator iterator = new BSTIterator(root);
     * while (iterator.hasNext()) {
     *    TreeNode node = iterator.next();
     *    do something for node
     * }
     */
    public class BSTIterator {
        //@param root: The root of binary tree.
        private Stack<TreeNode> stack = new Stack<TreeNode>();
        private TreeNode node = null;
        public BSTIterator(TreeNode root) {
            // write your code here
            node = root;
        }
    
        //@return: True if there has next node, or false
        public boolean hasNext() {
            // write your code here
            if (node != null) {
                TreeNode next = node;
                while (next != null) {
                    stack.push(next);
                    next = next.left;
                }
                node = null;
            }
            return !stack.empty();
        }
        //@return: return next node
        public TreeNode next() {
            // write your code here
            if (!hasNext()) {
                return null;
            }
            TreeNode curt = stack.pop();
            node = curt.right;
            return curt;
        }
    }
    View Code

    26.insert-node-in-a-binary-search-tree(在二叉查找树中插入节点)

    给定一棵二叉查找树和一个新的树节点,将节点插入到树中。你需要保证该树仍然是一棵二叉查找树。

    分治解法:

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root: The root of the binary search tree.
         * @param node: insert this node into the binary search tree
         * @return: The root of the new binary search tree.
         */
        public TreeNode insertNode(TreeNode root, TreeNode node) {
            // write your code here
            if (root == null) {
                return node;
            }
            if (root.val > node.val) {
                root.left = insertNode(root.left, node);
            } else {
                root.right = insertNode(root.right, node);
            }
            return root;
        }
    }
    View Code

    注意:要插入的节点跟root.val做比较后决定插入左子树还是右子树。if (root == null) {return node;}而不是return null。

    27.search-range-in-binary-search-tree(二叉查找树中搜索区间)

    给定两个值 k1 和 k2(k1 < k2)和一个二叉查找树的根节点。找到树中所有值在 k1 到 k2 范围内的节点。即打印所有x (k1 <= x <= k2) 其中 x 是二叉查找树的中的节点值。返回所有升序的节点值。

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root: The root of the binary search tree.
         * @param k1 and k2: range k1 to k2.
         * @return: Return all keys that k1<=key<=k2 in ascending order.
         */
        private ArrayList<Integer> result;
        public ArrayList<Integer> searchRange(TreeNode root, int k1, int k2) {
            // write your code here
            result = new ArrayList<Integer>();
            helper(root, k1, k2);
            return result;
        }
        private void helper(TreeNode root, int k1, int k2) {
            if (root == null) {
                return;
            }
            if (root.val > k1) {
                helper(root.left, k1, k2);
            }
            if (root.val >= k1 && root.val <= k2) {
                result.add(root.val);
            }
            if (root.val < k2) {
                helper(root.right, k1, k2);
            }
        }
    }
    View Code

    注意:因为要返回满足k1 <= x <= k2条件的所有升序x,所以采用中序遍历(左-根-右)。如果root.val > k,helper(root.left, k1, k2);如果root.val >= k1 && root.val <= k2) ,result.add(root.val);如果root.val < k2,helper(root.right, k1, k2)。

    28.remove-node-in-binary-search-tree(删除二叉查找树中的节点)【hard】

    给定一棵具有不同节点值的二叉查找树,删除树中与给定值相同的节点。如果树中没有相同值的节点,就不做任何处理。你应该保证处理之后的树仍是二叉查找树。

    /**
     * Definition of TreeNode:
     * public class TreeNode {
     *     public int val;
     *     public TreeNode left, right;
     *     public TreeNode(int val) {
     *         this.val = val;
     *         this.left = this.right = null;
     *     }
     * }
     */
    public class Solution {
        /**
         * @param root: The root of the binary search tree.
         * @param value: Remove the node with given value.
         * @return: The root of the binary search tree after removal.
         */
        public TreeNode removeNode(TreeNode root, int value) {
            // write your code here
            TreeNode dummy = new TreeNode(0);
            dummy.left = root;
            TreeNode parent = findNode(dummy, root, value);
            TreeNode node;
            if (parent.left != null && parent.left.val == value) {
                node = parent.left;
            } else if (parent.right != null && parent.right.val == value) {
                node = parent.right;
            } else {
                return dummy.left;
            }
            deleteNode(parent, node);
            return dummy.left;
        }
        private TreeNode findNode(TreeNode parent, TreeNode node, int value) {
            if (node == null) {
                return parent;
            }
            if (node.val == value) {
                return parent;
            }
            if (value < node.val) {
                return findNode(node, node.left, value);
            } else {
                return findNode(node, node.right, value);
            }
        }
        private void deleteNode(TreeNode parent, TreeNode node) {
            if (node.right == null) {
                if (parent.left == node) {
                    parent.left = node.left;
                } else {
                    parent.right = node.left;
                }
            } else {
                TreeNode temp = node.right;
                TreeNode father = node;
                while (temp.left != null) {
                    father = temp;
                    temp = temp.left;
                }
                if (father.left == temp) {
                    father.left = temp.right;
                } else {
                    father.right = temp.right;
                }
                if (parent.left == node) {
                    parent.left = temp;
                } else {
                    parent.right = temp;
                }
                temp.left = node.left;
                temp.right = node.right;
            }
        }
    }
    View Code

    29.sort-integers-ii(整数排序II)【要记住】

    给一组整数,按照升序排序。使用归并排序,快速排序,堆排序或者任何其他 O(n log n) 的排序算法。

    快速排序解法:

    public class Solution {
        /**
         * @param A an integer array
         * @return void
         */
        public void sortIntegers2(int[] A) {
            // Write your code here
            if (A == null || A.length == 0) {
                return;
            }
            quickSort(A, 0, A.length - 1);
        }
        private void quickSort(int[] A, int start, int end) {
            if (start >= end) {
                return;
            }
            int left = start;
            int right = end;
            int pivot = A[start + (end - start) / 2];
            while (left <= right) {
                while (left <= right && A[left] < pivot) {
                    left++;
                }
                while (left <= right && A[right] > pivot) {
                    right--;
                }
                if (left <= right) {
                    int temp = A[left];
                    A[left] = A[right];
                    A[right] = temp;
                    left++;
                    right--;
                }
            }
            quickSort(A, start, right);
            quickSort(A, left, end);
        }
    }
    View Code

    思想:分治,先整体有序再局部有序。1.从序列中挑出一个元素,作为基准(pivot),一般取中间位置;2.将原序列分为<=pivot,pivot,>=pivot的样子;3.递归进行以上的操作。

    注意:在开始位置>=结束位置时,要停止操作。

    归并排序解法:

    public class Solution {
        /**
         * @param A an integer array
         * @return void
         */
        public void sortIntegers2(int[] A) {
            // Write your code here
            if (A == null || A.length == 0) {
                return;
            }
            int[] temp = new int[A.length];
            mergeSort(A, 0, A.length - 1, temp);
        }
        private void mergeSort(int[] A, int start, int end, int[] temp) {
            if (start >= end) {
                return;
            }
            int mid = start + (end - start) / 2;
            mergeSort(A, start, mid, temp);
            mergeSort(A, mid + 1, end, temp);
            merge(A, start, mid, end, temp);
        }
        private void merge(int[] A, int start, int mid, int end, int[] temp) {
            int left = start;
            int right = mid + 1;
            int index = start;
            while (left <= mid && right <= end) {
                if (A[left] < A[right]) {
                    temp[index++] = A[left++];
                } else {
                    temp[index++] = A[right++];
                }
            }
            while (left <= mid) {
                temp[index++] = A[left++];
            }
            while (right <= end) {
                temp[index++] = A[right++];
            }
            for (int i = start; i <= end; i++) {
                A[i] = temp[i];
            }
        }
    }
    View Code

    思想:分治,先局部有序再整体有序。将两个已经排序的序列合并成一个序列。

    注意:在开始位置>=结束位置时,要停止操作。

    30.sort-integers(整数排序)

    给一组整数,按照升序排序,使用选择排序,冒泡排序,插入排序或者任何 O(n2) 的排序算法。

    冒泡排序解法:

    public class Solution {
        /**
         * @param A an integer array
         * @return void
         */
        public void sortIntegers(int[] A) {
            // Write your code here
            int n = A.length;
            for (int i = 0; i < n - 1; i++) {
                for (int j = 0; j < n - 1 - i; j++) {
                    if (A[j] > A[j + 1]) {
                        int temp = A[j];
                        A[j] = A[j + 1];
                        A[j + 1] = temp;
                    }
                }
            }
        }
    }
    View Code

    选择排序解法:

    public class Solution {
        /**
         * @param A an integer array
         * @return void
         */
        public void sortIntegers(int[] A) {
            // Write your code here
            int n = A.length;
            int min;
            for (int i = 0; i < n - 1; i++) {
                min = i;
                for (int j = i + 1; j < n; j++) {
                    if (A[j] < A[min]) {
                        min = j;
                    }
                }
                if (min != i) {
                    int temp = A[min];
                    A[min] = A[i];
                    A[i] = temp;
                }
            }
        }
    }
    View Code

    插入排序解法:

    public class Solution {
        /**
         * @param A an integer array
         * @return void
         */
        public void sortIntegers(int[] A) {
            // Write your code here
            int n = A.length;
            for (int i = 1; i < n; i++) {
                int temp = A[i];
                int j = i - 1;
                while (j >= 0 && A[j] > temp) {
                    A[j + 1] = A[j];
                    j--;
                }
                A[j + 1] = temp;
            }
        }
    }
    View Code
  • 相关阅读:
    FLEX,图标操作,xml, 通信,实例
    FLEX 合并两个XML的属性
    在内核中如何获得系统的日期和时间
    delphi中生成空格的函数
    Delphi中使用@取函数地址的问题
    vc中产生随机数
    delphi里label显示多行文本的两种方法
    360,傲游,诺顿最新版,网页溢出防护原理
    VC使用Zlib对内存流进行压缩与解压缩
    【TXPManifest控件】Delphi使用XP样式的按钮等控件
  • 原文地址:https://www.cnblogs.com/struggleli/p/6801032.html
Copyright © 2020-2023  润新知