这题放了很久,前几天去北京渣打玩了下,表示有点受打击,工程题还是没经验啊!有需要的可以问我要题。
这题还是比较巧的。(自我感觉)。eg: 7 5 6 4
首先分成两半 (7 5)(6 4)
接着再分成两半 (7)(5)(6)(4) //直到分成1份,即长度为1的子数组
然后合并,排序,统计 (5 7)(4 6) //长度为2了。
再合并,统计 (4 5 6 7) //长度为4了。
下面来讲下合并统计的过程,data数组中存了,((5 7)( 4 6))指针分别指向两段的结尾;
比较7和6,发现7大于6,所以把7放入新的数组copy,他的逆序数为后面的数组的当前大小即2;
接着指针前移,5比6小,把6放入新的数组,没有逆序数,接着同理5和4比较,5放入,逆序数为1;
最后把剩下的没放完的数组放入copy,递归;
说的简单,写代码这种事还是得亲身尝试才可以!!!
链接:http://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5?rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
#include<stdio.h> #include<vector> using namespace std; class Solution { public: int InversePairs(vector<int> data) { if(data.size()<=0) return NULL; vector<int> copy(data); //拷贝data int cnt=InversePairs(data,copy,0,data.size()-1); //多态 return cnt; } int InversePairs(vector<int> &data,vector<int> ©,int start,int end) { if(start==end) //结束条件 { copy[start]=data[start]; return 0; } int len=(end-start)/2; int left=InversePairs(copy,data,start,start+len); int right=InversePairs(copy,data,start+len+1,end); //前半段最后一个数字下标 int i=start+len; //后半段最后一个数字下标 int j=end; //当前指针 int indexCopy=end; int cnt=0; //计算这一段内逆序数的个数 while(i>=start && j>=start+len+1) { if(data[i]>data[j]) { copy[indexCopy--]=data[i--];//copy用来复制存新的数组 cnt+=j-start-len;//记录前数组在后数组中的逆序个数 } else { copy[indexCopy--]=data[j--];//否则copy等于后面的数组往下放 } }//出while表示前半段已经没有后半段的逆序数了。然后把剩余的存起来 for(;i>=start;--i) { copy[indexCopy--]=data[i]; } for(;j>=start+len+1;--j) { copy[indexCopy--]=data[j]; } return left+right+cnt; } }; int main() { Solution so; vector<int> ve; ve.push_back(7); ve.push_back(5); ve.push_back(6); ve.push_back(4); int cnt=so.InversePairs(ve); printf("%d\n",cnt); return 0; }