求大牛帮忙解下谷歌面试算法题

u013249074 2014-03-21 04:48:05
怎样快速的在数组a[1..N]中找到m个数 ( m<N ),使得这m个数的和是小于M的最大数 ,若不存在这样的m个数,返回0
输入 :第一行有两个数:N,M
第二行有数组a的N个元素:
Sample:1
Input :
3 11
4 5 10
Output:9

Sample:2
Input :
3 6
4 5 10
Output:0
...全文
228 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
u013249074 2014-03-23
  • 打赏
  • 举报
回复
引用 13 楼 TBWood 的回复:
不用给分啦,重在解答哈。不是为了分数啦。~~祝你好运。
额,非常感谢,能麻烦你再帮我看看 http://bbs.csdn.net/topics/390739167?page=1#post-397011609 这道算法题吗
u013249074 2014-03-22
  • 打赏
  • 举报
回复
@ 7楼 :你这是回溯法啊,回溯法我会的,时间复杂度是指数的,太大了,一旦N=10或者以上就很难了;还是谢谢你; @ 8楼:不能套用背包问题,这题我写出了按照背包问题求解思路的解法,但对于大一点的数就不行了,举个例子吧: Input : 6 ( N ) 4 ( m ) 10000 ( M ) 4 500 1999 9021 14 8723 按背包问题思路求解的算法时间复杂度是O ( N * M * m ) ,很明显,从6个数找出4个满足条件的数,用这么大的时间来计算时不合理的
FancyMouse 2014-03-22
  • 打赏
  • 举报
回复
引用 5 楼 u013249074 的回复:
0-1背包问题肯定不行啊,因为背包问题中物品的个数没有限制;还有一点,题目没有提到数组的元素是不是正数,我们就不能想当然的认为他一定就是正数,你说对吗? 所以,就不能给分了,不过还是非常感谢你~
背包有各种版本,模型都可以套。物品个数有限制的一样能做。负数的一样能做。
tbwork 2014-03-22
  • 打赏
  • 举报
回复
昨晚下班了~~ 今天写了下代码,这类题都是属于 背包空间分配的 衍生问题,稍微作下变通就好理解啦 // ACMtpl.cpp : 定义控制台应用程序的入口点。 #include "StdAfx.h" #include <iostream> using namespace std; #define N 6 // 个数 #define M 13 //背包大小 #define m 3 // 物品个数限制 #define NINF -9999999 //极小值 代表无解 int arr[N] ={ 1,2,3,4,5,10}; // 搜索数组 /* 0-1背包使用递归实现 从最后一个物品开始考虑,问题转换为: 设当前 待搜索数组前i个元素 物品个数限制curm 背包剩余容量 curM 那问题转换为 : (1)如果选当前物品,子问题为: 求 前 i-1 个元素中 curm-1个元素相加的和 是小于 curM-当前物品大小 的最大值。 (2)如果不选择物品,子问题为: 求 前 i-1个元素中 curm 个元素相加的和是小于 curM 的最大值 然后使用记忆化优化该递归,或者使用DP改写该递归算法 算法复杂度为 N*m*M */ int sum(int j) { int re=0; for(int i=0;i<=j;i++) re+=arr[i]; return re; } int rem[N][m+1][M+1]; int rec(int i, int curm, int curM ) { if(rem[i][curm][curM]!= -1) return rem[i][curm][curM]; if( curm==0) return 0; //当背包占满时 直接退出 if (i<0) return NINF; // 当物品搜索完毕,背包还没有满,那么不符合题意,返回 无解 if( (i+1) < curm ) return NINF; // 无解 if( i == (curm-1)) return sum(i)<curM ? sum(i) : NINF; int a,b; //分别记录取 和不取 下的值 if(arr[i] <= curM) { //取 int temp =rec(i-1, curm-1,curM-arr[i]); a = ( temp== NINF ? NINF : arr[i]+ temp); } else { //为满足条件,不取 a = rec(i-1, curm, curM); } b= rec( i-1,curm, curM); //分支 , 不取 rem[i][curm][curM]=max(a,b); //记忆 return rem[i][curm][curM]; } void main() { memset(rem,-1,N*(m+1)*(M+1)*sizeof(int)); if(m>N) cout<< 0; int result=rec(N-1,m,M); if(result==NINF) { cout<<"无解"<<endl; } else { cout<<result<<endl; } }
tbwork 2014-03-22
  • 打赏
  • 举报
回复
不用给分啦,重在解答哈。不是为了分数啦。~~祝你好运。
u013249074 2014-03-22
  • 打赏
  • 举报
回复
引用 10 楼 TBWood 的回复:
are you kidding ? DP也只能到这个复杂度,而且DP是稳定这个复杂度。 我充分相信考官要的就是这个答案(DP肯定也对)。 另外这和回溯法不搭边,请自行学习记忆化搜索。 我写的这个算法对于你上面说的 6 4 10000 ,最多只需要 2^6 次。 这里的 NMm是 当 2^N 大于 该值时。 准确的来说,复杂度应该是 min { NMm, 2^N}; 你先把算法读一遍,再说合理不合理啊。
不好意思啊,刚开始随便看了下,以为是回溯法的左右子树呢,这方法应该可以了,就是当M太大时,内存占用太多,不能能否尝试用bitset改善内存 ,对了,怎么给分啊,我第一次用,不会给分。。。
FancyMouse 2014-03-22
  • 打赏
  • 举报
回复
引用 9 楼 u013249074 的回复:
@ 7楼 :你这是回溯法啊,回溯法我会的,时间复杂度是指数的,太大了,一旦N=10或者以上就很难了;还是谢谢你; @ 8楼:不能套用背包问题,这题我写出了按照背包问题求解思路的解法,但对于大一点的数就不行了,举个例子吧: Input : 6 ( N ) 4 ( m ) 10000 ( M ) 4 500 1999 9021 14 8723 按背包问题思路求解的算法时间复杂度是O ( N * M * m ) ,很明显,从6个数找出4个满足条件的数,用这么大的时间来计算时不合理的
你如果不想复杂度里出现M,那N肯定会出现在指数函数的指数上。你选一个?
tbwork 2014-03-22
  • 打赏
  • 举报
回复
are you kidding ? DP也只能到这个复杂度,而且DP是稳定这个复杂度。 我充分相信考官要的就是这个答案(DP肯定也对)。 另外这和回溯法不搭边,请自行学习记忆化搜索。 我写的这个算法对于你上面说的 6 4 10000 ,最多只需要 2^6 次。 这里的 NMm是 当 2^N 大于 该值时。 准确的来说,复杂度应该是 min { NMm, 2^N}; 你先把算法读一遍,再说合理不合理啊。
tbwork 2014-03-21
  • 打赏
  • 举报
回复
我的疏忽。。对,个数有限制。我再研究下。。。。
u013249074 2014-03-21
  • 打赏
  • 举报
回复
0-1背包问题肯定不行啊,因为背包问题中物品的个数没有限制;还有一点,题目没有提到数组的元素是不是正数,我们就不能想当然的认为他一定就是正数,你说对吗? 所以,就不能给分了,不过还是非常感谢你~
tbwork 2014-03-21
  • 打赏
  • 举报
回复
如果有 负数 那就 不能这么做了。。。。应该没负数吧??? 如果有负数,题目应该这么问, 求连续的序列,和 是小于M的最大值。。。
tbwork 2014-03-21
  • 打赏
  • 举报
回复
好简单。算法复杂度 o(n^2) 先去做下这道题: 0-1背包 给你 N个物品, 每个物品的 体积vi 和 价值 wi, 现在有一个 背包 体积为 M,求背包能最多放多少价值的物品。 这道面试题就更加简单了。 把 0-1 背包问题中的 物品 的 体积 和价值 设置为同一个值 就行了。 解决方法: (1) 递归+记忆化搜索优化 (3) 动态规划
u013249074 2014-03-21
  • 打赏
  • 举报
回复
哎,错了,m=2忘记写了,M=11;
derekrose 2014-03-21
  • 打赏
  • 举报
回复
3 11 4 5 10 为什么是9不是10??

65,209

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧