lintcode阶梯训练第三关(九章)

595、Binary Tree Longest Consecutive Sequence

  • 题目
    Given a binary tree, find the length of the longest consecutive sequence path.
    The path refers to any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The longest consecutive path need to be from parent to child (cannot be the reverse).
    【来一遍~】
    样例
    For example,
    1
    . \
    .. 3
    . / \
    . 2 4
    …… \
    ……. 5
    Longest consecutive sequence path is 3-4-5, so return 3.
    . 2
    .. \
    … 3
    .. /
    . 2
    /
    1
    Longest consecutive sequence path is 2-3,not3-2-1, so return 2.

  • 代码

public class Solution {
    private int longest = 0;
    public int longestConsecutive(TreeNode root) {
        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 subtreeMax = 1;
        if (root.left != null && root.val + 1 == root.left.val) {
            subtreeMax = Math.max(left + 1, subtreeMax);
        }
        if (root.right != null && root.val + 1 == root.right.val) {
            subtreeMax = Math.max(right + 1, subtreeMax);
        }
        longest = Math.max(subtreeMax, longest);
        return subtreeMax;
    }
}

614、Binary Tree Longest Consecutive Sequence II

  • 题目
    Given a binary tree, find the length of the longest consecutive sequence path.
    The path could be start and end at any node in the tree
    【再来遍~】
    样例
    1
    / \
    2 0
    /
    3
    Return 4 // 0-1-2-3-4

  • 代码

class ResultType {
    public int up, down, len;
    public ResultType(int len, int up, int down) {
        this.len = len;
        this.up = up;
        this.down = down;
    }
}
public class Solution {
    public int longestConsecutive2(TreeNode root) {
        if (root == null) {
            return 0;
        }
        ResultType result = helper(root);
        return result.len;
    }
    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 up = 0;
        int down = 0;
        if (root.left != null && root.left.val + 1 == root.val) {
            up = Math.max(up, left.up + 1);
        }
        if (root.left != null && root.val + 1 == root.left.val) {
            down = Math.max(down, left.down + 1);
        }
        if (root.right != null && root.right.val + 1 == root.val) {
            up = Math.max(up, right.up + 1);
        }
        if (root.right != null && root.val + 1 == root.right.val) {
            down = Math.max(down, right.down + 1);
        }
        int len = down + up + 1;
        len = Math.max(len, Math.max(left.len, right.len));
        return new ResultType(len, up, down);
    }
}

596、Minimum Subtree

  • 题目
    Given a binary tree, find the subtree with minimum sum. Return the root of the subtree.
    注意事项
    LintCode will print the subtree which root is your return node.
    It’s guaranteed that there is only one subtree with minimum sum and the given binary tree is not an empty tree.
    样例
    Given a binary tree:
    …. 1
    … / \
    . -5 2
    . / \ / \
    0 2 -4 -5
    return the node 1.

  • 代码

public class Solution {
    private TreeNode subtree = null;
    private int minSum = Integer.MAX_VALUE;
    public TreeNode findSubtree(TreeNode root) {
        helper(root);
        return subtree;
    }
    private int helper(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = helper(root.left);
        int right = helper(root.right);
        int sum = left + right + root.val;
        if (sum < minSum) {
            minSum = sum;
            subtree = root;
        }
        return sum;
    }
}

597、Subtree with Maximum Average

  • 题目
    Given a binary tree, find the subtree with maximum average. Return the root of the subtree.
    【再来遍~】
    注意事项
    LintCode will print the subtree which root is your return node.
    It’s guaranteed that there is only one subtree with maximum average.
    样例
    Given a binary tree:
    ….. 1
    …. / \
    . -5 11
    . / \ / \
    1 2 4 -2
    return the node 11.

  • 代码

/**
 * 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 {
    private class ResultType {
        public int size;
        public int sum;
        public ResultType(int size, int sum) {
            this.size = size;
            this.sum = sum;
        }
    }
    private TreeNode subtree = null;
    private ResultType subtreeResult = null;
    public TreeNode findSubtree2(TreeNode root) {
        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.size + right.size + 1, left.sum + right.sum + root.val);
        if (subtree == null || result.sum * subtreeResult.size > result.size * subtreeResult.sum) {
            subtreeResult = result;
            subtree = root;
        }
        return result;
    }
}

475、二叉树的最大路径和 II

  • 题目
    给一棵二叉树,找出从根节点出发的路径中,和最大的一条。
    这条路径可以在任何二叉树中的节点结束,但是必须包含至少一个点(也就是根了)。
    样例
    给出如下的二叉树:
    1
    / \
    2 3
    返回4。(最大的路径为1→3)

  • 代码

public class Solution {
    public int maxPathSum2(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = maxPathSum2(root.left);
        int right = maxPathSum2(root.right);
        return Math.max(0, Math.max(left, right)) + root.val;
    }
}

376、二叉树的路径和

  • 题目
    给定一个二叉树,找出所有路径中各节点相加总和等于给定 目标值 的路径。
    一个有效的路径,指的是从根节点到叶节点的路径。
    【再来遍~】
    样例
    给定一个二叉树,和 目标值 = 5:
    . 1
    . / \
    . 2 4
    / \
    2 3
    返回:
    [
    [1, 2, 2],
    [1, 4]
    ]

  • 代码

public class Solution {
    public List<List<Integer>> binaryTreePathSum(TreeNode root, int target) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if (root == null) {
            return result;
        }
        List<Integer> list = new ArrayList<>();
        list.add(root.val);
        helper(root, target, root.val, list, result);
        return result;
    }
    private void helper(TreeNode root,
                        int target,
                        int sum,
                        List<Integer> list,
                        List<List<Integer>> result) {
        if (root.left == null && root.right == null) {
            if (sum == target) {
                result.add(new ArrayList<Integer>(list));
            }
        }
        if (root.left != null) {
            list.add(root.left.val);
            helper(root.left, target, sum + root.left.val, list, result);
            list.remove(list.size() - 1);
        }
        if (root.right != null) {
            list.add(root.right.val);
            helper(root.right, target, sum + root.right.val, list, result);
            list.remove(list.size() - 1);
        }
    }
}

480、二叉树的所有路径

  • 题目
    给一棵二叉树,找出从根节点到叶子节点的所有路径。
    样例
    给出下面这棵二叉树:
    1
    / \
    2 3
    . \
    .. 5
    所有根到叶子的路径为:
    [
    “1->2->5”,
    “1->3”
    ]

  • 代码

public class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> result = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        if (root == null) {
            return result;
        }
        list.add(root.val);
        helper(root, list, result);
        return result;
    }
    private void helper(TreeNode root,
                        List<Integer> list,
                        List<String> result) {
        if (root.left == null && root.right == null) {
            result.add(toStr(new ArrayList<Integer>(list)));
        }
        if (root.left != null) {
            list.add(root.left.val);
            helper(root.left, list, result);
            list.remove(list.size() - 1);
        }
        if (root.right != null) {
            list.add(root.right.val);
            helper(root.right, list, result);
            list.remove(list.size() - 1);
        }
    }
    private String toStr(List<Integer> list) {
        StringBuilder sb = new StringBuilder();
        sb.append(list.get(0));
        for (int i = 1; i < list.size(); i++) {
            sb.append("->");
            sb.append(list.get(i));
        }
        return sb.toString();
    }
}

这个方法再来遍~

public class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        List<String> left = binaryTreePaths(root.left);
        List<String> right = binaryTreePaths(root.right);
        for (String l : left) {
            result.add(root.val + "->" + l);
        }
        for (String r : right) {
            result.add(root.val + "->" + r);
        }
        if (result.size() == 0) {
            result.add("" + root.val);
        }
        return result;
    }
}

453、将二叉树拆成链表

  • 题目
    将一棵二叉树按照前序遍历拆解成为一个假链表。所谓的假链表是说,用二叉树的 right 指针,来表示链表中的 next 指针。
    【再来遍~】
    注意事项
    不要忘记将左儿子标记为 null,否则你可能会得到空间溢出或是时间溢出。
    样例
    …. … 1
    ….. …. \
    1 ……. 2
    / \ …… \
    2 5 => 3
    / \ \ … … \
    3 4 6 …… 4
    ……….. .. … \
    ……….. … … 5
    ………… … … \
    ……….. . … … 6

  • 代码

public class Solution {
    private TreeNode lastNode = null;
    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        }
        if (lastNode != null) {
            lastNode.left = null;
            lastNode.right = root;
        }
        lastNode = root;
        TreeNode right = root.right;
        flatten(root.left);
        flatten(right);
    }
}

public class Solution {
    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
            if (stack.isEmpty()) {
                node.right = null;
            } else {
                node.right = stack.peek();
            }
            node.left = null;
        }
    }
}

public class Solution {
    public void flatten(TreeNode root) {
        helper(root);
        return;
    }
    private TreeNode helper(TreeNode root) {
        if (root == null) {
            return root;
        }
        TreeNode leftLast = helper(root.left);
        TreeNode rightLast = helper(root.right);
        if (leftLast != null) {
            leftLast.right = root.right;
            root.right = root.left;
            root.left = null;
        }
        if (rightLast != null) {
            return rightLast;
        }
        if (leftLast != null) {
            return leftLast;
        }
        return root;
    }
}

378、将二叉查找树转换成双链表

  • 题目
    将一个二叉查找树按照中序遍历转换成双向链表。
    【再来遍】
    样例
    给定一个二叉查找树:
    .. 4
    . / \
    . 2 5
    / \
    1 3
    返回 1<->2<->3<->4<->5。

  • 代码

/**
 * 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 {
    public DoublyListNode first;
    public DoublyListNode last;
    public ResultType(DoublyListNode first, DoublyListNode last) {
        this.first = first;
        this.last = last;
    }
}
public class Solution {
    public DoublyListNode bstToDoublyList(TreeNode root) {
        if (root == null) {
            return null;
        }
        ResultType result = helper(root);
        return result.first;
    }
    private ResultType helper(TreeNode root) {
        if (root == null) {
            return null;
        }
        ResultType left = helper(root.left);
        ResultType right = helper(root.right);
        DoublyListNode node = new DoublyListNode(root.val);
        ResultType result = new ResultType(null, null);
        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;
            node.next = right.first;
            right.first.prev = node;
        }
        return result;
    }
}

93、平衡二叉树

  • 题目
    给定一个二叉树,确定它是高度平衡的。对于这个问题,一棵高度平衡的二叉树的定义是:一棵二叉树中每个节点的两个子树的深度相差不会超过1。
    样例
    给出二叉树 A={3,9,20,#,#,15,7}, B={3,#,20,15,7}
    A) 3 ….. B) 3
    … / \ ……….. \
    .. 9 20 …….. 20
    …… / \ …….. / \
    …..15 7 …. 15 7
    二叉树A是高度平衡的二叉树,但是B不是

  • 代码

public class Solution {
    public boolean isBalanced(TreeNode root) {
        return helper(root) != -1;
    }
    private int helper(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = helper(root.left);
        int right = helper(root.right);
        if (left == -1 || right == -1) {
            return -1;
        }
        if (Math.abs(left - right) > 1) {
            return -1;
        }
        return Math.max(left, right) + 1;
    }
}

95、验证二叉查找树

  • 题目
    给定一个二叉树,判断它是否是合法的二叉查找树(BST)
    一棵BST定义为:
    节点的左子树中的值要严格小于该节点的值。
    节点的右子树中的值要严格大于该节点的值。
    左右子树也必须是二叉查找树。
    一个节点的树也是二叉查找树。
    【再来遍】
    样例
    一个例子:
    2
    / \
    1 4
    .. / \
    .. 3 5
    上述这棵二叉树序列化为 {2,1,4,#,#,3,5}.

  • 代码

public class Solution {
    private boolean isFirst = true;
    private int lastVal = Integer.MAX_VALUE;
    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }
        if (!isValidBST(root.left)) {
            return false;
        }
        if (!isFirst && lastVal >= root.val) {
            return false;
        }
        isFirst = false;
        lastVal = root.val;
        if (!isValidBST(root.right)) {
            return false;
        }
        return true;
    }
}

97、二叉树的最大深度

  • 题目
    给定一个二叉树,找出其最大深度。
    二叉树的深度为根节点到最远叶子节点的距离。
    样例
    给出一棵如下的二叉树:
    1
    / \
    2 3
    .. / \
    . 4 5
    这个二叉树的最大深度为3.

  • 代码

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

155、二叉树的最小深度

  • 题目
    给定一个二叉树,找出其最小深度。
    二叉树的最小深度为根节点到最近叶子节点的距离。
    样例
    给出一棵如下的二叉树:
    1
    / \
    2 3
    .. / \
    . 4 5
    这个二叉树的最小深度为 2

  • 代码

public class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = minDepth(root.left);
        int right = minDepth(root.right);
        if (left == 0) {
            return right + 1;
        }
        if (right == 0) {
            return left + 1;
        }
        return Math.min(left, right) + 1;
    }
}

66、二叉树的前序遍历

  • 题目
    给出一棵二叉树,返回其节点值的前序遍历。
    样例
    给出一棵二叉树 {1,#,2,3},
    1
    . \
    .. 2
    . /
    3
    返回 [1,2,3].

  • 代码

public class Solution {
    private ArrayList<Integer> ans;
    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ans = new ArrayList<Integer>();
        helper(root);
        return ans;
    }
    private void helper(TreeNode root) {
        if (root == null) {
            return;
        }
        ans.add(root.val);
        helper(root.left);
        helper(root.right);
    }
}

非递归【再来遍】

public class Solution {
    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> ans = new ArrayList<>();
        if (root == null) {
            return ans;
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            ans.add(node.val);
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
        return ans;
    }
}

67、二叉树的中序遍历

  • 题目
    给出一棵二叉树,返回其中序遍历
    样例
    给出一棵二叉树 {1,#,2,3},
    1
    . \
    .. 2
    . /
    3
    返回 [1,3,2].

  • 代码

public class Solution {
    public ArrayList<Integer> inorderTraversal(TreeNode root) {
        ArrayList<Integer> ans = new ArrayList<>();
        helper(root, ans);
        return ans;
    }
    private void helper(TreeNode root, ArrayList<Integer> ans) {
        if (root == null) {
            return;
        }
        helper(root.left, ans);
        ans.add(root.val);
        helper(root.right, ans);
    }
}

非递归【再来遍】

public class Solution {
    public ArrayList<Integer> inorderTraversal(TreeNode root) {
        ArrayList<Integer> ans = new ArrayList<>();
        if (root == null) {
            return ans;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curt = root;
        while (curt != null || !stack.isEmpty()) {
            while (curt != null) {
                stack.push(curt);
                curt = curt.left;
            }
            curt = stack.pop();
            ans.add(curt.val);
            curt = curt.right;
        }
        return ans;
    } 
}

68、二叉树的后序遍历

  • 题目
    给出一棵二叉树,返回其后序遍历
    样例
    给出一棵二叉树 {1,#,2,3},
    1
    . \
    .. 2
    . /
    3
    返回 [3,2,1]

  • 代码

public class Solution {
    public ArrayList<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> ans = new ArrayList<>();
        if (root == null) {
            return ans;
        }
        ArrayList<Integer> left = postorderTraversal(root.left);
        ArrayList<Integer> right = postorderTraversal(root.right);
        ans.addAll(left);
        ans.addAll(right);
        ans.add(root.val);
        return ans;
    }
}

448、二叉树查找树中序后继

  • 题目
    给一个二叉查找树(什么是二叉查找树),以及一个节点,求该节点的中序遍历后继,如果没有返回null
    【再来遍】
    注意事项
    It’s guaranteed p is one node in the given tree. (You can directly compare the memory address to find p)
    样例
    给出 tree = [2,1] node = 1:
    2
    /
    1
    返回 node 2.
    给出 tree = [2,1,3] node = 2:
    2
    / \
    1 3
    返回 node 3.

  • 代码

public class Solution {
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        TreeNode successor = null;
        while (root != null && root != p) {
            if (root.val > p.val) {
                successor = root;
                root = root.left;
            } else {
                root = root.right;
            }
        }
        if (root == null) {
            return null;
        }
        if (root.right == null) {
            return successor;
        }
        root = root.right;
        while (root.left != null) {
            root = root.left;
        }
        return root;
    }
}

88、最近公共祖先

  • 题目
    给定一棵二叉树,找到两个节点的最近公共父节点(LCA)。
    最近公共祖先是两个节点的公共的祖先节点且具有最大深度。
    注意事项
    假设给出的两个节点都在树中存在
    样例
    对于下面这棵二叉树
    4
    / \
    3 7
    .. / \
    .. 5 6
    LCA(3, 5) = 4
    LCA(5, 6) = 7
    LCA(6, 7) = 7

  • 代码

public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
        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;
    }
}

474、最近公共祖先 II

  • 题目
    给一棵二叉树和二叉树中的两个节点,找到这两个节点的最近公共祖先LCA。
    两个节点的最近公共祖先,是指两个节点的所有父亲节点中(包括这两个节点),离这两个节点最近的公共的节点。
    每个节点除了左右儿子指针以外,还包含一个父亲指针parent,指向自己的父亲。
    样例
    对于下面这棵二叉树
    4
    / \
    3 7
    .. / \
    .. 5 6
    LCA(3, 5) = 4
    LCA(5, 6) = 7
    LCA(6, 7) = 7

  • 代码

/**
 * Definition of ParentTreeNode:
 * 
 * class ParentTreeNode {
 *     public ParentTreeNode parent, left, right;
 * }
 */
public class Solution {
    public ParentTreeNode lowestCommonAncestorII
                      (ParentTreeNode root,
                       ParentTreeNode A,
                       ParentTreeNode B) {
        ArrayList<ParentTreeNode> pathA = getPath(A);
        ArrayList<ParentTreeNode> pathB = getPath(B);
        int indexA = pathA.size() - 1;
        int indexB = pathB.size() - 1;
        ParentTreeNode ancestor = null;
        while (indexA >= 0 && indexB >= 0) {
            if (pathA.get(indexA) != pathB.get(indexB)) {
                break;
            }
            ancestor = pathA.get(indexA);
            indexA--;
            indexB--;
        }
        return ancestor;
    }
    private ArrayList<ParentTreeNode> getPath(ParentTreeNode node) {
        ArrayList<ParentTreeNode> list = new ArrayList<>();
        while (node != null) {
            list.add(node);
            node = node.parent;
        }
        return list;
    }
}

578、最近公共祖先 III

  • 题目
    给一棵二叉树和二叉树中的两个节点,找到这两个节点的最近公共祖先LCA。
    两个节点的最近公共祖先,是指两个节点的所有父亲节点中(包括这两个节点),离这两个节点最近的公共的节点。
    返回 null 如果两个节点在这棵树上不存在最近公共祖先的话。
    注意事项
    这两个节点未必都在这棵树上出现。
    样例
    对于下面这棵二叉树
    4
    / \
    3 7
    .. / \
    .. 5 6
    LCA(3, 5) = 4
    LCA(5, 6) = 7
    LCA(6, 7) = 7
    LCA(5, 8) = null

  • 代码

class ResultType {
    public TreeNode node;
    public boolean existA, existB;
    public ResultType(TreeNode node, boolean existA, boolean existB) {
        this.node = node;
        this.existA = existA;
        this.existB = existB;
    }
}
public class Solution {
    public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) {
        ResultType result = helper(root, A, B);
        if (result.existA && result.existB) {
            return result.node;
        } else {
            return null;
        }
    }
    private ResultType helper(TreeNode root, TreeNode A, TreeNode B) {
        if (root == null) {
            return new ResultType(null, false, false);
        }
        ResultType left = helper(root.left, A, B);
        ResultType right = helper(root.right, A, B);
        boolean exist_A = left.existA || right.existA || root == A;
        boolean exist_B = left.existB || right.existB || root == B;
        if (root == A || root == B) {
            return new ResultType(root, exist_A, exist_B);
        }
        if (left.node != null && right.node != null) {
            return new ResultType(root, exist_A, exist_B);
        }
        if (left.node != null) {
            return new ResultType(left.node, exist_A, exist_B);
        }
        if (right.node != null) {
            return new ResultType(right.node, exist_A, exist_B);
        }
        return new ResultType(null, exist_A, exist_B);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值