谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做?

来源:互联网 发布:自动成语接龙软件 编辑:程序博客网 时间:2024/04/25 09:54

分析:

 “假设两个整数数组为A和B,各有N个元素,任意两个数的和组成的数组C有N^2个元素。   那么可以把这些和看成N个有序数列:          A[1]+B[1] <= A[1]+B[2] <= A[1]+B[3] <=…          A[2]+B[1] <= A[2]+B[2] <= A[2]+B[3] <=…          …         A[N]+B[1] <= A[N]+B[2] <= A[N]+B[3] <=…    问题转变成,在这N^2个有序数列里,找到前k小的元素”
在网上看到相关分析,就如上面的分析所述:A[i1] + B[j1] 和A[i2] + B[j2],在i1和i2,j1和j2这四个数不一样的情况下,根本无法确定谁大谁小,比如A[3] + B[0]和A[1] + B[1],所以单纯地比较A中的i1和i2或者B中的j1和j2都是会有问题的。我想这个题的思路可以是:

1、在A中选k个最小值,并排序(升序)

2、在B中选k个最小值,并排序(升序)

3、再在这些数中,进行相关操作。

部分代码如下:

#include<iostream>#include<vector>#include<algorithm>using namespace std;typedef struct sum_info{int value;int i;int j;}sum_info;bool cmp(sum_info a,sum_info b){return a.value < b.value;}//判断ai,bj这两个数的和有没有必要加入q这个容器里,如果ai的下标和bj的下标在q中已经有比他们小的加和存在了那么就没有必要了bool IsBig(vector<sum_info> q, int ai, int bj){for(int i = 0; i < q.size(); i++){sum_info tmp = q.at(i);if(tmp.i <= ai && tmp.j <= bj)return true;}return false;}int *min_k(int *A,int *B,int k, int length){if(A==NULL||B==NULL||k<=0)return NULL;vector<sum_info> q;//利用C++的STL,其中存放的是目前为止备选的最小和sum_info tmp;tmp.value=A[0]+B[0];tmp.i=0;tmp.j=0;q.push_back(tmp);//起始时,只有A[0]+B[0]int *result=new int[k];//存储结果的数据int count,i,j;count=0;//计数用while(count<k){tmp=q.at(0);//取出第一个元素q.erase(q.begin());result[count++]=tmp.value;i=tmp.i;j=tmp.j;//接下来的操作是关键,就是看是否将a[i+1]+b[j] 和 a[i]+b[j+1]加入到q中,这里就需要遍历q了sum_info a,b;if((i+1)<length && !IsBig(q,i+1,j)){a.i=i+1;a.j=j;a.value=A[i+1]+B[j];q.push_back(a);}if((j+1)<length && !IsBig(q,i,j+1)){b.i=i;b.j=j+1;b.value=A[i]+B[j+1];q.push_back(b);}sort(q.begin(),q.end(),cmp);}return result;}int main(){int A[]={2, 8, 9, 15};int B[]={1, 9, 11, 12};int *result=min_k(A,B,16,4);if(result!=NULL){for(int i=0;i<16;i++)cout<<result[i]<<" ";cout<<endl;delete []result;}return 0;}
这个代码的重点,就是保持原有的在取了A[i]+B[j]的和之后,再选择A[i+1]+B[j]和A[i]+B[j+1],但是不能简简单单选择,需要进行一定的判断。 其实可以在纸上画一画自己如果计算时,所用的思路。然后就能在程序中进行刻画了。


                                             
0 0
原创粉丝点击