315. Count of Smaller Numbers After Self

You are given an integer array nums and you have to return a new counts array. 
The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i]. Example: Given nums = [5, 2, 6, 1] To the right of 5 there are 2 smaller elements (2 and 1). To the right of 2 there is only 1 smaller element (1). To the right of 6 there is 1 smaller element (1). To the right of 1 there is 0 smaller element. Return the array [2, 1, 1, 0].

bst: 加count记住遍历过得点有几个点比当前的点小(作为当前节点的左子树的节点数), 返回右父节点的所有count 和, 向左遍历(想好建好树后最后的点向哪遍历, 向左遍历, 第一个点就遍历了右边的所有的节点)

Time: O(NlogN), space: O(N) better than naive solution O(N^2)

public class Solution {
    private class TreeNode {
        public int val;
        public int count = 1;
        public TreeNode left, right;
        
        public TreeNode(int val) {
            this.val = val;
        }
    }
    
    public List<Integer> countSmaller(int[] nums) {
        List<Integer> res = new ArrayList<>();
        if(nums == null || nums.length == 0) {
            return res; 
        }
        TreeNode root = new TreeNode(nums[nums.length - 1]);
        res.add(0);
        
        for(int i = nums.length - 2; i >= 0; i--) {
            int count = addNode(root, nums[i]);
            res.add(count);
        }
        
        Collections.reverse(res);
        return res;
    }
    
    private int addNode(TreeNode root, int val) {
        int curCount = 0;
        while(true) {
            if(val <= root.val) {
                root.count++;                   // add the inversion count
                if(root.left == null) {
                    root.left = new TreeNode(val);
                    break;
                } else {
                    root = root.left;
                }
            } else {
                curCount += root.count;
                if(root.right == null) {
                    root.right = new TreeNode(val);
                    break;
                } else {
                    root = root.right;
                }
            }
        }
        
        return curCount;
    }
}

  

Merge sort: 老难了, 还是用bst吧

public class Solution {
    int[] count;// 记录坐标的count
   //记录排序后的坐标, 就是nums[index[i]] 为排序后的值
    public List<Integer> countSmaller(int[] nums) {
        List<Integer> ans = new ArrayList<>();
        if (nums == null || nums.length == 0) {
            return ans;
        }
        count = new int[nums.length];
         int[] index = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            index[i] = i;
        }
        mergSort(nums, 0, nums.length - 1, index);
        for (int i = 0; i < nums.length; i++) {
            ans.add(count[i]);
        }
        return ans;
        
    }
    private void mergSort(int[] nums, int start, int end, int[] index)  {
        if (end <= start) return;
        int mid = start + (end - start) / 2;
        mergSort(nums, start, mid, index);
        mergSort(nums, mid + 1, end, index);
        merg(nums, start, end, index);
    }
    private void merg(int[] nums, int start, int end, int[] index) {
        int mid = start + (end - start) / 2;
        int left = start, right = mid + 1, newStart = 0, sum = 0;
        int[] newIndex = new int[end - start + 1]; // 对坐标排序
        while (left <= mid && right <= end) {
            if (nums[index[right]] < nums[index[left]]) {
                sum++;
                newIndex[newStart++] = index[right++];
            } else  {
                count[index[left]] += sum;
                newIndex[newStart++] = index[left++];
            }
        }
        while (left <= mid) {
            count[index[left]] += sum;
            newIndex[newStart++] = index[left++];
        } 
        while (right <= end) {
            newIndex[newStart++] = index[right++];
        }
        for (int i = start; i <= end; i++) {
            index[i] = newIndex[i - start];
        }
        
    }
}

  

posted @ 2017-08-07 11:36  apanda009  阅读(187)  评论(0编辑  收藏  举报