创新工厂笔试题

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.马戏团排练叠罗汉节目,一个人站在另外一个人上面,要求上面的人要比下面的人矮一点且轻一点,编程计算这个马戏团最高可以叠多少层。

posted @ 2012-11-12 20:57  Mr.Rico  阅读(432)  评论(0编辑  收藏  举报