小和问题和逆序对问题
小和问题,
在一个数组中,每一个数左边的数中比当前数小的数累加起来,叫做这个数组的小和,求一个数组的小和
直接遍历:
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;
}
使用归并
求小和的问题可以等效为:
如求下面数组的小和
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大,23
4右边有1个数比4大,14
2右边有1个数比2大,12
5右边没有数比5大,05
加起来41+23+14+12+05=16
在编写代码时与一般的归并有一点不一样,当左侧数组p1和右侧数组p2指向的数一样时先拷贝右侧的数,不然不知道有多少个数比左侧p1指向的数大,会有漏算的情况,其中process中 if (L >= R) return 0;//此处我认为是递归的中止条件,很多次忘记加这个条件导致无法出结果
务必别丢
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;
}
逆序对问题
在一个数组中,左边的数如果比右边的数大,则两个数构成一个逆序对,请打印所有的逆序对
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;
}