谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做?
2015-04-14 15:27
567 查看
分析:
“假设两个整数数组为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 +B[1] <= A +B[2] <= A +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],但是不能简简单单选择,需要进行一定的判断。 其实可以在纸上画一画自己如果计算时,所用的思路。然后就能在程序中进行刻画了。
相关文章推荐
- 谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做?
- 谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做?
- 输入一个递增的数组和一个数字s,找出数组中任意两个数使他们的和正好是这个数字s,如果有任意多对数字的和为s,输出任意一堆数字即可,例如,输入数组[1,2,4,7,11,15]和数字
- 《剑指Offer》输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
- 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
- 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 陈利人 面试题 对于一个n位正整数a,去掉其中任意k(k<=n)个数字后,剩下的数字按原次序排列可以组成一个新的正整数。设计一个删数算法,使得剩下的数字组成的正整数最小。
- 输入一个字符串,将其中的连续数字字符组成整数,并放入数组中,在主函数中打印这个数组及数组的个数。
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 【剑指offer24】输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 给定一个整数数组,两个数字的返回索引将它们加到一个特定的目标中。 您可以假设每个输入都只有一个解决方案,并且您可能不会两次使用相同的元素。
- 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%100000000
- 二货小易有一个W*H的网格盒子,网格的行编号为0~H-1,网格的列编号为0~W-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。 对于两个格子坐标(x1,y1),(x2,y2)的欧几里得距离为: ( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) 的算术平方根 小易想知道最多可以放多少块蛋糕在网格盒子里。 输入描述: 每组数组包含网格长宽W,
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- java 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 输入一个升序数组和一个整数,在数组里面找两个数使它们相加的和为这个整数
- 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。