问题可以通过将数组分成子范围,然后对这些子范围进行排序来解决。让我们详细看一下,
给定数组 =
[10, 12, 8, 17, 3, 24, 19]
现在将数组划分为长度为
4
的子范围,并按如下所示对这些子范围进行排序,
子范围排序数组
.................... ...............
| 8 | 10 | 12 | 17 | | 3 | 19 | 24 |
.................... ...............
2 0 1 3 4 6 5 => index
让我们来看一下子范围排序数组的第一个条目,即8
,并尝试找到大于8
的右侧元素数量。
正如您在上面看到的那样,8
属于第一个子范围,因为子范围已经排序,子范围中的元素按升序排列,但不按其索引顺序排列。这意味着在当前子范围中,我们必须将所有右侧元素的索引与元素8
的索引进行比较。
< p >
8
的索引是
2
,但是
10
的索引是
0
,这意味着
10
在输入数组中在
8
的左侧,
12
的索引也比
8
的索引小,这意味着
12
在输入数组中在
8
的左侧,
17
的索引是
3
,大于
8
的索引,这意味着
17
在输入数组中在
8
的右侧,可以被视为更大的元素,
在比较当前子范围内所有右侧元素的索引与
8
的索引后,右侧更大的元素
count = 1
,让我们看看下一个范围,
在子范围8
之后,情况完全改变了,现在我们知道这个子范围位于元素8
所属的子范围的右侧,这意味着我们不必将8
的索引与此范围中的元素进行比较,所有元素都在元素8
的右侧,我们只需要找到有多少个大于8
的元素,
现在我们将右子范围的第一个元素与8
进行比较,正如您在上面看到的,第一个元素是3
,小于8
,但是如果右子范围的第一个元素大于当前元素,则我们可以直接将计数器增加到右子范围中存在的元素数量。
因为第一个元素3
小于8
,所以我们在右侧子范围内找到8
的上限,即19
,而右侧子范围内的所有元素都大于8
,因此有两个元素19,24
,所以计数增加了2
,变成了count=3
最终,比元素8
大的右侧元素有3
个。
通过类似的方式,可以找到所有元素的右侧大于的元素数量,结果数组将是,
x(A) = [4, 3, 3, 2, 2, 0, 0]
结论是,通过将输入数组分成排序的子范围,可以按以下步骤找到右侧的更大元素。
- 比较当前子范围内所有正确元素的索引,
- 比较右子范围的第一个元素,如果:
i. 第一个元素大于当前元素,则右侧范围的所有元素都大于当前元素,
ii. 第一个元素小于当前元素,则在右子范围中找到当前元素的上限,并且从右子范围中的上限开始的元素都大于当前元素。
- 对所有右子范围重复步骤2。
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using std::cout;
std::vector<std::pair<int, std::size_t>> arrayOfSortedSubRange(std::size_t subRangeSize,
const std::vector<int>& numArr){
std::vector<std::pair<int, std::size_t>> res;
res.reserve(numArr.size());
for(std::size_t i = 0, numArrSize = numArr.size(); i < numArrSize; ++i){
res.emplace_back(numArr[i], i);
}
for(std::vector<std::pair<int, std::size_t>>::iterator it = res.begin(), endIt = res.end(); endIt != it;){
std::vector<std::pair<int, std::size_t>>::iterator rangeEndIt = it + std::min<std::ptrdiff_t>(endIt - it,
subRangeSize);
std::sort(it, rangeEndIt, [](const std::pair<int, std::size_t>& a, const std::pair<int, std::size_t>& b){
return a.first < b.first;});
it = rangeEndIt;
}
return res;
}
std::size_t rightGreterElmentCountOfNumber(int num, std::vector<std::pair<int, std::size_t>>::const_iterator rightSubRangeIt,
std::vector<std::pair<int, std::size_t>>::const_iterator endIt){
std::size_t count = 0;
std::vector<std::pair<int, std::size_t>>::const_iterator subRangEndIt = rightSubRangeIt +
std::min<std::ptrdiff_t>(endIt - rightSubRangeIt, 4);
while(endIt != rightSubRangeIt){
if(rightSubRangeIt->first > num){
count += subRangEndIt - rightSubRangeIt;
}
else{
count += subRangEndIt -
std::upper_bound(rightSubRangeIt, subRangEndIt, num, [](int num,
const std::pair<int, std::size_t>& element){ return num < element.first;});
}
rightSubRangeIt = subRangEndIt;
subRangEndIt += std::min<std::ptrdiff_t>(endIt - subRangEndIt, 4);
}
return count;
}
std::vector<std::size_t> rightGreaterElementCountForLessThanFiveNumbers(const std::vector<int>& numArr){
std::vector<std::size_t> res(numArr.size(), 0);
std::vector<std::size_t>::iterator resIt = res.begin();
for(std::vector<int>::const_iterator it = numArr.cbegin(), lastIt = it + (numArr.size() - 1); lastIt != it;
++it, ++resIt){
*resIt = std::count_if(it + 1, numArr.cend(), [num = *it](int rightNum){return rightNum > num;});
}
return res;
}
std::vector<std::size_t> rightGreaterElementCount(const std::vector<int>& numArr){
if(numArr.size() < 5){
return rightGreaterElementCountForLessThanFiveNumbers(numArr);
}
std::vector<std::size_t> resArr(numArr.size(), 0);
std::vector<std::pair<int, std::size_t>> subRangeSortedArr = arrayOfSortedSubRange(4, numArr);
for(std::vector<std::pair<int, std::size_t>>::const_iterator it = subRangeSortedArr.cbegin(),
endIt = subRangeSortedArr.cend(); endIt != it;){
std::vector<std::pair<int, std::size_t>>::const_iterator rightNextSubRangeIt = it + std::min<std::ptrdiff_t>(
endIt - it, 4);
for(std::vector<std::pair<int, std::size_t>>::const_iterator eleIt = it; rightNextSubRangeIt != eleIt; ++eleIt){
std::size_t count = std::count_if(eleIt, rightNextSubRangeIt, [index = eleIt->second](
const std::pair<int, std::size_t>& element){ return index < element.second;});
if(endIt != rightNextSubRangeIt){
count += rightGreterElmentCountOfNumber(eleIt->first, rightNextSubRangeIt, endIt);
}
resArr[eleIt->second] = count;
}
it += std::min<std::ptrdiff_t>(endIt - it, 4);
}
return resArr;
}
int main(){
std::vector<std::size_t> res = rightGreaterElementCount({10, 12, 8, 17, 3, 24, 19});
cout<< "[10, 12, 8, 17, 3, 24, 19] => [";
std::copy(res.cbegin(), res.cbegin() + (res.size() - 1), std::ostream_iterator<std::size_t>(cout, ", "));
cout<< res.back()<< "]\n";
}
输出:
[10, 12, 8, 17, 3, 24, 19] => [4, 3, 3, 2, 2, 0, 0]