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].

含义:针对一个数组,找到每一位的右面有多少个数小于它的值,没有的话就是0,返回数组

思路一:从后往前用二分插入法来倒排数组,后面的数字个数即为比当前数字小的数字

 

 1     public List<Integer> countSmaller(int[] nums) {
 2         int[] smaller = new int[nums.length];
 3         for(int i=nums.length-2; i>=0; i--) {
 4 //            从后往前遍历nums,采用二分插入排序的方式,将数组进行降序排列
 5 // 取出nums[i]后保存到temp,从i+1到末尾间找到nums[i]应该存在的位置(从i+1到末尾是降序排列),比如是left
 6             int left = i+1;
 7             int right = nums.length-1;
 8             while (left<=right) {
 9                 int m = (left+right)/2;
10                 if (nums[i] > nums[m]) right = m - 1;
11                 else left = m + 1;
12             }
13             smaller[i] = nums.length - left; //left后面的所有数都比nums[i]小
14             int temp = nums[i];
15             for(int j=i; j<right; j++) nums[j] = nums[j+1]; //把i和right之间的数据依次往前移动,空出right位置用于放置nums[i]
16             nums[right] = temp;
17         }

            return Arrays.stream(smaller)
                         .boxed()
                         .collect(Collectors.toList());

21     }

 

方法二:

 1 public class Solution {
 2     private class TreeNode {
 3         public int val;
 4         public int count = 1;
 5         public TreeNode left, right;
 6 
 7         public TreeNode(int val) {
 8             this.val = val;
 9         }
10     }
11 
12     public List<Integer> countSmaller(int[] nums) {
13 //        构造一棵二分搜索树,稍有不同的地方是我们需要加一个变量smaller来记录比当前节点值小的所有节点的个数,我们每插入一个节点,会判断其和根节点的大小,
14 //        如果新的节点值小于根节点值,则其会插入到左子树中,我们此时要增加根节点的smaller,并继续递归调用左子节点的insert。
15 //        如果节点值大于根节点值,则需要递归调用右子节点的insert并加上根节点的smaller,并加1
16         
17         List<Integer> res = new ArrayList<>();
18         if(nums == null || nums.length == 0) {
19             return res;
20         }
21         TreeNode root = new TreeNode(nums[nums.length - 1]);
22         res.add(0);
23 
24         for(int i = nums.length - 2; i >= 0; i--) {
25             int count = addNode(root, nums[i]);
26             res.add(count);
27         }
28 
29         Collections.reverse(res);
30         return res;
31     }
32 
33     private int addNode(TreeNode root, int val) {
34         int curCount = 0;
35         while(true) {
36             if(val <= root.val) {
37                 root.count++;                   // add the inversion count
38                 if(root.left == null) {
39                     root.left = new TreeNode(val);
40                     break;
41                 } else {
42                     root = root.left;
43                 }
44             } else {
45                 curCount += root.count;
46                 if(root.right == null) {
47                     root.right = new TreeNode(val);
48                     break;
49                 } else {
50                     root = root.right;
51                 }
52             }
53         }
54 
55         return curCount;
56     }

 

posted @ 2017-10-25 18:58  daniel456  阅读(157)  评论(0编辑  收藏  举报