[LeetCode] 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 1:

Input: nums = [5,2,6,1]
Output: [2,1,1,0]
Explanation:
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.

Example 2:

Input: nums = [-1]
Output: [0]

Example 3:

Input: nums = [-1,-1]
Output: [0,0]

Constraints:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104

计算右侧小于当前元素的个数。

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元素的数量。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/count-of-smaller-numbers-after-self
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题意是给一个数组,请你返回一个等长的 list,表示当前位置的右侧小于 nums[i] 的元素个数。

暴力解是O(n^2)的复杂度,肯定是不行的。我这里给出一个二分法思路。创建一个跟 input 数组等长的 arr 数组记录结果,同时再创建一个空的 list 做插入排序。数组从右往左扫描,对于每一个元素,我们把他插入到 list 一个合适的位置,使得 list 最后依然是升序排列的。这个插入的动作,比较高效的做法就是用二分。这个元素当时被插入list的index,同时也是这个元素的右侧有多少个元素小于他自己的个数。

跑一个例子,nums = [5,2,6,1]。一开始插入 input 数组的最后一个元素1的时候,由于此时 list 为空,所以插入 1 的时候,他在 list 的 index 是 0,而且在原数组中最后一个元素的右边没有比他更小的元素了;接着我们再试图把6放入list,此时他在list的index会是1(list = {1, 6}),说明在原数组中,6的右侧有一个元素比他小。

时间O(nlogn)

空间O(n)

Java实现

 1 class Solution {
 2     public List<Integer> countSmaller(int[] nums) {
 3         // 返回结果
 4         List<Integer> res = new ArrayList<>();
 5         // 数组长度为0,直接返回
 6         if (nums.length == 0) {
 7             return res;
 8         }
 9         // 为了提高效率,新建一个数组型的返回结果
10         int[] arr = new int[nums.length];
11         // 新建一个list,用于排序
12         List<Integer> list = new ArrayList<>();
13         // 从数组最后一位开始向前循环
14         for (int i = nums.length - 1; i >= 0; i--) {
15             // 当前数字
16             int num = nums[i];
17             // 将当前数字插入到新建list中
18             // 使用二分查找找到插入位置
19             int left = 0;
20             int right = list.size() - 1;
21             while (left <= right) {
22                 int mid = (left + right) / 2;
23                 if (num <= list.get(mid)) {
24                     right = mid - 1;
25                 } else {
26                     left = mid + 1;
27                 }
28             }
29             // 将当前数字插入到相应位置,保证list升序排列
30             list.add(left, num);
31             // 当前位置前所有数字均小于当前数字,将个数加入返回结果
32             arr[i] = left;
33         }
34         // 将list转化为数组
35         for (int count : arr) {
36             res.add(count);
37         }
38         return res;
39     }
40 }

 

JavaScript实现

 1 /**
 2  * @param {number[]} nums
 3  * @return {number[]}
 4  */
 5 var countSmaller = function(nums) {
 6     let res = [];
 7     // corner case
 8     if (nums == null || nums.length == 0) {
 9         return nums;
10     }
11 
12     // normal case
13     let len = nums.length;
14     let arr = new Array(len).fill(0);
15     let list = [];
16     for (let i = len - 1; i >= 0; i--) {
17         let num = nums[i];
18         let left = 0;
19         let right = list.length - 1;
20         while (left <= right) {
21             let mid = Math.floor(left + (right - left) / 2);
22             if (num <= list[mid]) {
23                 right = mid - 1;
24             } else {
25                 left = mid + 1;
26             }
27         }
28         list.splice(left, 0, num);
29         arr[i] = left;
30     }
31     for (let count of arr) {
32         res.push(count);
33     }
34     return res;
35 };

 

相关题目

315. Count of Smaller Numbers After Self

1365. How Many Numbers Are Smaller Than the Current Number

LeetCode 题目总结

posted @ 2020-10-06 01:58  CNoodle  阅读(303)  评论(0编辑  收藏  举报