leetcode 315 Count of Smaller Numbers After Self

題目細節描述參看leetcode。java

今天的重頭戲 LC315 Count of Smaller Numbers After Self.
在講這個題目以前,請思考這個問題。在BST找到全部比Node P小的節點個數。
利用inorder tarvseral咱們一直走BST並計數,找到p點就返回計數獲得的值。時間複雜度worst case O(n).若是咱們要找到的是好多節點的值,若是還用這種方法,時間複雜度就是O(k*n).
這裏咱們有大量重複的工做,每次都從leftmost走,直到找到這個node Pi. 實際上咱們能夠預處理這個BST。把每一個節點小於它的個數記錄下來。綜合的時間複雜度就是O(n+klogn).node

要快速找到比本身小的數,就能夠創建一個BST來幫助咱們。
咱們創建的Node(int val, int dup, int leftsum,Node left, Node right) 其中dup解決重複值的問題,leftsum記錄左子樹的節點數。
給一個[3,2,2,6,1],構建出的樹長這樣,其中Node.val(dup, leftsum)表示每一個節點。ui

1(1,0)
            \
             6(1,3)
            /
         2(2,0)
             \
              3(1,0)

創建的細節待會兒再講。
假如咱們的輸入變爲[5,3,2,2,6,1]要找比5小的怎麼辦?
首先1比5小,total = 1+0. 走到6發現比5大,去到2,發現5比2大,total += 2 +0。去到3,發現5比3大,total += 1+0, 最後total = 4.
假如咱們的輸入變爲[7,3,2,2,6,1]要找比5小的怎麼辦?
首先1比7小,total = 1+0. 走到6發現比7發,total += 1+3, total = 5。code

給定要找的點P,這裏的規律就是,往右下走,說明當前點和當前的的左子樹的值所有比P.val小。咱們計數。
往左下走,咱們不知道下面節點是否比p小,須要再重複上面的判斷。直到找到全部比p小的節點數。leetcode

給定一個這樣咱們自定義的BST,咱們直到如何找到。下面就是如何構造了。
仍是上面那個圖。咱們加入5這個點,在走到6的時候,是走到6的左子樹,這是6的左子樹應該+1,變成:get

1(1,0)
            \
             6(1,4)
            /
         2(2,0)
             \
              3(1,0)  
                \
                 5(1,0)

這是加入左子樹的狀況,如今再繼續加入7這個點。咱們走到6要向右,這是左子樹沒變化,6這裏也不變。
和上面的例子稍有不一樣,咱們連續加入了5,7這兩個點。io

1(1,0)
            \
             6(1,4)
            /    \
         2(2,0)    7(1,0)
             \
              3(1,0)  
                \
                 5(1,0)

咱們能夠試着返回小於7的節點數,也就是每次向右走的時候,node上的值求和。total = 1+0 + 1+4 = 6。class

代碼以下。List

public class Solution {
    class Node {
        Node left, right;
        int val, sum, dup = 1;
        public Node(int v) {
            val = v;
        }
    }
    public List<Integer> countSmaller(int[] nums) {
        Integer[] ans = new Integer[nums.length];
        Node root = null;
        for (int i = nums.length - 1; i >= 0; i--) {
            root = insert(nums[i], root, ans, i, 0);
        }
        return Arrays.asList(ans);
    }
    private Node insert(int num, Node node, Integer[] ans, int i, int preSum) {
        if (node == null) {
            node = new Node(num);
            ans[i] = preSum;
        } else if (node.val == num) {
            node.dup++;
            ans[i] = preSum + node.sum;
        } else if (node.val > num) {
            node.sum++;
            node.left = insert(num, node.left, ans, i, preSum);
        } else {
            node.right = insert(num, node.right, ans, i, preSum + node.dup + node.sum);
        }
        return node;
    }
}

代碼來源: leetcode mayanist
https://discuss.leetcode.com/...方法

相關文章
相關標籤/搜索