저자: Zhai Tianbao Steven
저작권 설명: 저작권은 저자에게 있습니다.상업적 전재의 경우 저자에게 허가를 요청하십시오.비상업적 전재의 경우 출처를 표시하십시오.
제목 설명:
배열의 두 숫자는 이전 숫자가 다음 숫자보다 크면 두 숫자가 역쌍을 이룹니다. 배열을 입력하고 이 배열에서 역방향 쌍의 총 수 P를 찾으십시오. 그리고 P 모듈로 1000000007의 결과를 출력합니다. 즉, 출력 P mod 1000000007
데이터 범위: 데이터의 50%에 대해 size≤104
데이터의 100%에 대해 size≤105
배열의 모든 숫자 값은 0≤val≤109를 만족합니다.
요구 사항: 공간 복잡도 O(n), 시간 복잡도 O(nlogn)
예:
입력하다:
[1,2,3,4,5,6,7,0]
반환 값:
7
문제 해결 아이디어:
이 문제에 대한 기존의 해결책은 폭력적인 방법이지만 이 문제는 nlogn의 복잡성이 필요하므로 병합 정렬로 해결할 수 있습니다.
- 병합 정렬을 정상적으로 작성하십시오.
- Combined Sorting 병합 및 정렬 과정에서 두 하위 구간의 데이터를 차례로 비교하여 새로운 순서를 재구성하는데 이때 왼쪽의 값 A가 오른쪽의 값 B보다 크면 A에서 중간 위치 C Add로 직접 데이터 수를 전송할 수 있습니다. 하위 범위가 정렬되었기 때문에 A가 B보다 크므로 A와 C 사이의 모든 데이터가 B보다 커야 하므로 역순 쌍이 형성될 수 있습니다.
- 이러한 방식으로 시간 복잡성은 주제의 요구 사항을 충족합니다.
테스트 코드:
class Solution {
public:
int mod = 1000000007;
// 归并排序
int mergeSort(vector<int>& data, int left, int right){
// 停止
if(left >= right)
return 0;
// 中间位
int mid = (left + right) / 2;
// 拆分合并,累加逆序对数量
int count = mergeSort(data, left, mid) + mergeSort(data, mid + 1, right);
count %= mod;
// 排序
int i = left, j = mid + 1;
vector<int> temp(data);
for(int t = left; t <= right; ++t){
// i如果到了mid+1,说明左子区间遍历完毕,后续直接取右区间数据即可
if(i == mid + 1){
data[t] = temp[j];
j++;
}
// j如果到了right+1,说明右子区间遍历完毕,后续直接取左区间数据即可
// 如果左侧值小于右侧值,不符合逆序对,正常排序即可
else if(j == right + 1 || temp[i] <= temp[j]){
data[t] = temp[i];
i++;
}
// 如果左侧值大于右侧值,说明左侧当前位置到左子区间结束的数值,都大于该右侧值,直接计算数量:mid-i+1;然后正常排序
// 这样操作降低了时间复杂度
else{
data[t] = temp[j];
j++;
count += mid - i + 1;
}
}
return count % mod;
}
// 逆序对
int InversePairs(vector<int>& nums) {
int size = static_cast<int>(nums.size());
int count = mergeSort(nums, 0, size - 1);
return count;
}
};