小和问题和逆序对问题
小和问题,
在一个数组中,每一个数左边的数中比当前数小的数累加起来,叫做这个数组的小和,求一个数组的小和
直接遍历:
cpp
int littleSum1(int* arr, int L, int R)
{
int temp = 0;
for (int i = L; i < R + 1; i++)
{
for (int j = L; j < i; j++)
{
if (arr[j] < arr[i])
{
temp = temp + arr[j];
}
}
}
return temp;
}
使用归并
求小和的问题可以等效为:
如求下面数组的小和
cpp
int arr[] = { 1,3,4,2,5 };
通常的思路:
1左边没有比1小的
3左边比3小的:1
4左边比4小的:1,3
2左边比2小的:1
5左边比5小的:1,3,4,2
加起来:1+1+3+1+1+3+4+2=16
等效为:
1右边有4个数比1大,则会小和中有4个1,41
3右边有2个数比3大,2 3
4右边有1个数比4大,14
2右边有1个数比2大,1 2
5右边没有数比5大,05
加起来4 1+23+1 4+12+05=16
在编写代码时与一般的归并有一点不一样,当左侧数组p1和右侧数组p2指向的数一样时先拷贝右侧的数,不然不知道有多少个数比左侧p1指向的数大,会有漏算的情况,其中process中if (L >= R) return 0;//此处我认为是递归的中止条件,很多次忘记加这个条件导致无法出结果
务必别丢
cpp
int littleSum2(int* arr, int L, int R)
{
if (L >= R) return 0;
return process(arr, L, R);
}
int process(int* arr, int L, int R)
{
if (L >= R) return 0;//此处我认为是递归的中止条件,很多次忘记加这个条件导致无法出结果
int mid = L + ((R - L) >> 1);
return process(arr, L, mid)+ process(arr, mid + 1, R)+merge_sum(arr, L, mid, R);
}
int merge_sum(int* arr, int L, int mid, int R)
{
int res = 0;
int i = 0;
int p1 = L;
int p2 = mid + 1;
int* temp = new int[R - L + 1];
while (p1 <= mid && p2 <= R)
{
if (arr[p1] < arr[p2])
{
res = res + (R - p2 + 1) * arr[p1];
temp[i++] = arr[p1++];
}
else
{
temp[i++] = arr[p2++];
}
}
while (p1 <= mid)
{
temp[i++] = arr[p1++];
}
while (p2 <= R)
{
temp[i++] = arr[p2++];
}
for (int j = 0; j < R-L + 1; j++)
{
arr[L+j] = temp[j];
}
delete[] temp;
return res;
}
逆序对问题
在一个数组中,左边的数如果比右边的数大,则两个数构成一个逆序对,请打印所有的逆序对
cpp
void Reverse_pair(int* arr, int L, int R)
{
if (L >= R)
{
cout << "无逆序对" << endl;
return;
}
processReverse(arr, L, R);
}
void processReverse(int* arr, int L, int R)
{
if (L >= R)
return;
int mid = L + ((R - L) >> 1);
processReverse(arr, L, mid);
processReverse(arr, mid + 1, R);
mergeReverse(arr, L, mid, R);
}
void mergeReverse(int* arr, int L, int mid, int R)
{
int i = 0;
int* temp = new int[R - L + 1];
int p1 = L;
int p2 = mid + 1;
while (p1 <= mid && p2 <= R)
{
if (arr[p1] > arr[p2])
{
temp[i] = arr[p1];
cout << "逆序对:" << arr[p1] << " " << arr[p2] << endl;
i = i + 1;
p1 = p1 + 1;
}
else
{
temp[i++] = arr[p2++];
}
}
while (p1 <= mid)
{
temp[i++] = arr[p1++];
}
while (p2 <= R)
{
temp[i++] = arr[p2++];
}
for (int j = 0; j < R - L + 1; j++)
{
arr[L + j] = temp[j];
}
delete[] temp;
}