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
原文地址:https://www.cnblogs.com/struggleli/p/6801032.html