题目地址:点击打开链接
题目描述:You are given an integer array nums and you have to return a newcounts array. The counts array has the property where counts[i]
is the number of smaller elements to the right ofnums[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]
.
一开始直接就用暴力比较,但超时了。代码如下:
class Solution {
public:
vector<int> countSmaller(vector<int>& nums) {
int l=nums.size();
if(l==0)return nums;
vector<int> c;
int num=0;
for(int i=0;i<l-1;i++){
for(int j=i+1;j<l;j++){
if(nums[i]>nums[j])num++;
}
c.push_back(num);
num=0;
}
c.push_back(0);
return c;
}
};
在论坛中发现一个简单的代码,虽然accept了但是很多人认为O(n^2)的复杂度并不好:
0
class Solution {
public:
vector<int> countSmaller(vector<int>& nums) {
vector<int> db;
vector<int> result(nums.size());
for(int i = nums.size()-1; i >= 0; i--)
{
auto it = lower_bound(db.begin(), db.end(), nums[i]);
result[i] = it - db.begin();
db.insert(it, nums[i]);
}
return result;
}
};
正确的代码如下:
class Solution {
protected:
void merge_countSmaller(vector<int>& indices, int first, int last, vector<int>& results, vector<int>& nums) {
int count = last - first;
if (count > 1) {
int step = count / 2;
int mid = first + step;
merge_countSmaller(indices, first, mid, results, nums);
merge_countSmaller(indices, mid, last, results, nums);
vector<int> tmp;
tmp.reserve(count);
int idx1 = first;
int idx2 = mid;
int semicount = 0;
while ((idx1 < mid) || (idx2 < last)) {
if ((idx2 == last) || ((idx1 < mid) &&
(nums[indices[idx1]] <= nums[indices[idx2]]))) {
tmp.push_back(indices[idx1]);
results[indices[idx1]] += semicount;
++idx1;
} else {
tmp.push_back(indices[idx2]);
++semicount;
++idx2;
}
}
move(tmp.begin(), tmp.end(), indices.begin()+first);
}
}
public:
vector<int> countSmaller(vector<int>& nums) {
int n = nums.size();
vector<int> results(n, 0);
vector<int> indices(n, 0);
iota(indices.begin(), indices.end(), 0);
merge_countSmaller(indices, 0, n, results, nums);
return results;
}
};