版权声明:本文为博主原创文章,欢迎转载!转载请保留原博客地址。 https://blog.csdn.net/grllery/article/details/88918657
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:
Input: [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.
题目:求解nums[i]
右侧元素中比nums[i]
小的元素的个数count[i]
。
思路:参见solution using merge sort with explanation。题目的本质上同LeetCode493. Reverse Pairs。利用归并排序,求nums[i]
右侧元素中比nums[i]
本身小的元素的个数,相当于在并的过程中,左侧数组nums[i]
合并到数组merge
之前,发生了由右侧数组元素先添加到merge
中的次数。这里有个技巧,我们排序的过程中,不改变元素数组nums
,而是改变nums[i]
对应的下标。
class Solution {
public:
vector<int> countSmaller(vector<int>& nums) {
int n = nums.size();
vector<int> res(n), index(n);
for(int i=0; i < n; ++i){
index[i] = i;
}
countSmaller(nums, index, res, 0, n-1);
return res;
}
private:
void countSmaller(vector<int>& nums, vector<int>& index, vector<int>& res, int l, int r){
if(l >= r) return;
int m = l + (r - l)/2;
countSmaller(nums, index, res, l, m);
countSmaller(nums, index, res, m+1, r);
vector<int> merge(r-l+1);
int i = l, j = m + 1, k = 0, p = 0;
while(i <= m && j <=r){
if(nums[index[i]] > nums[index[j]]){
merge[k++] = index[j++];
p++;
}
else{
res[index[i]] += p;
merge[k++] = index[i++];
}
}
while(i <= m){
res[index[i]] += p;
merge[k++] = index[i++];
}
while(j <= r){
merge[k++] = index[j++];
}
copy(merge.begin(), merge.end(), index.begin() + l);
}
};