[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