1. 逆序对
问题:对于一个包含N个非负整数的数组A[1..n],如果有i<j,且A[i]>A[j],则称(A[i] ,A[j])为数组A中的一个逆序对。
例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个。
方法一:最原始的方法,利用两重循环进行枚举。该算法的时间复杂度为O(n^2)。
方法二:利用归并排序的思想求解逆序对的个数,这是目前解决该问题的一种较为高效的算法。该算法的时间复杂度为O(nlogn)。
#include <iostream> #include <algorithm> #include <iterator> #include <cstdlib> using namespace std; int reverse1(int a[],int n){ int count=0; for(int i=0;i<n-1;i++){ for(int j=i+1;j<n;j++) if(a[i]>a[j]) count++; } return count; } int merge(int a[],int l,int m,int r){ int count=0; int *b=new int[r-l+1]; int k=0; int i=l,j=m+1; while(i<=m&&j<=r){ if(a[i]>a[j]) { count+=(m-i+1); b[k++]=a[j++]; } else b[k++]=a[i++]; } while(i<=m) b[k++]=a[i++]; while(j<=r) b[k++]=a[j++]; for(i=0;i<r-l+1;i++) a[l+i]=b[i]; copy(b,b+r-l+1,ostream_iterator<int>(cout," ")); cout<<" count="<<count; cout<<endl; delete[] b; return count; } int rev_merge(int a[],int l,int r){ if(l<r){ int m=(l+r)/2; int n1=rev_merge(a,l,m); int n2=rev_merge(a,m+1,r); int n3=merge(a,l,m,r); return n1+n2+n3; } return 0; } int reverse2(int a[],int n){ return rev_merge(a,0,n-1); } int main(){ const int n=10; int a[n]; for(int i=0;i<n;i++) a[i]=rand()%100; copy(a,a+n,ostream_iterator<int>(cout," ")); cout<<endl; cout<<reverse1(a,n)<<endl; cout<<reverse2(a,n)<<endl; copy(a,a+n,ostream_iterator<int>(cout," ")); cout<<endl; }
1.现有面值为1分、2分、5分、10分的硬币任意多个,编程计算组成n分钱有多少总组合方法。
2.马戏团排练叠罗汉节目,一个人站在另外一个人上面,要求上面的人要比下面的人矮一点且轻一点,编程计算这个马戏团最高可以叠多少层。