数组中的逆序对
题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如,有一个数组为Array[0..n] 其中有元素a[i],a[j].如果 当i<j时,a[i]>a[j],那么我们就称(a[i],a[j])为一个逆序对。在数组{7,5,6,4}中一共存在5对逆序对,分别是(7,6),(7,5),(7,4),(6,4),(5,4)。
花了很长时间想还是没有想出来怎么做,怎么也不服气。。。
最后还是折服了,上网查。。。
才看到文章的 “排序算法汇总->归并排序”这句话的时候,兴奋不已(你妹啊!分治法~)。。
放弃继续看下去的念头,立马动笔。。。
心未平息,洋洋洒洒的codes,问题一堆,接着只有IDE写。。
发现思路已经出了问题,亡羊补牢为时未晚。。。
逐静心细想,直接上机,N次的debug之后。。。
才完成最终的代码。。。。
#include <iostream> using namespace std; int merge(int a[], int s, int e) { int *tmp; int mid, lend, rend, i, j, k; int lc, cnt, snum, tlc; // lc for left count, cnt for count, tlc for temporary left count if (s>=e) { return 0; } mid = s+ (e-s)/2; tmp = (int *)malloc(sizeof(int)* (e-s+1)); i = s; j = mid+1; lend = mid; rend = e; lc = 0; cnt = 0; k = 0; snum = 0; //same num while(i<=lend && j<=rend) { if (a[i]<a[j]) { snum = a[j]; while(j<=rend && a[j]==snum) { tmp[k++] = a[j++]; cnt += lc; } } else if (a[i]> a[j]) { snum = a[i]; while(i<=lend && a[i]== snum) { tmp[k++] = a[i++]; lc++; } } else //if same { tlc = 0 ; snum = a[i]; while(i<=lend && a[i]== snum) { tmp[k++] = a[i++]; tlc++; } while(j<=rend && a[j]==snum) { tmp[k++] = a[j++]; cnt += lc; } lc += tlc; } } if (j<= rend && tmp[k]== a[j]) //上次最后两个是相等的 { while(j<= rend && tmp[k]== a[j]) { cnt += lc - tlc; tmp[k++] = a[j++]; } } while(j<= rend) { cnt += lc; tmp[k++] = a[j++]; } while (i<= lend ) { tmp[k++] = a[i++]; } memcpy(&a[s], tmp, sizeof(int)* (e-s+1)); free(tmp); return cnt; } int func(int a[], int s, int e) { int mid, lcnt, rcnt,mcnt; if (s>=e) { return 0; } mid = s+ (e-s)/2; lcnt = func(a, s, mid); rcnt = func(a, mid+1, e); mcnt = merge(a, s, e); return lcnt+ rcnt + mcnt; } int main() { // int a1[] = {7,5,6,2}; int a1[] = {1,3,7,6,6,5,5,4,6,5}; cout<<func(a1, 0, sizeof(a1)/sizeof(int)-1)<<endl; return 0; }
之后和同学一番吐槽,忽闻说有使用快速排序的思想。
基本思路:先是记录没一个的元素的位置,然后根据比较的时候,移动时判断两个位置之间的关系。
排序可以升序或降序(看你怎么处理了),假设我们使用排升序,
要比较两个数,大者放在key前,否则之后;
比如:a[i]和a[j],i<j,如果a[i]<a[j], a[j]移key前,a[i]移到key后;因为i<j,所以不是逆序对;
否则,a[j]移key后,a[i]移到key前,是逆序对。
例子:
array:2 3 1
pos:1 2 3
比较3和1,因为3的位置为2,而1的位置为3,即1在3后,说明它们是逆序对
array:2 3 1
pos:1 2 3
比较并对换了3和2,因为3的位置为2,而2的位置为1,即3在2后,说明它们不是逆序对
array:3 2 1
pos:2 1 3
到此完成了排序,结果也出来了。
P.S. 算法思路过于死板,未能灵活利用各种算法的思想,发散思维。
未能静心分析,过早落于细节,混淆思维。
这题目花了我太多的时间,感觉真不值,效率啊~需要好好总结!
毕