2012搜狐的算法题(求助)

tangbiaoms 2011-09-26 10:27:31
搜狐的最后一个算法题,求高手帮忙解答一下。
给定一个实数数组,按序排列(从小到大),从数组从找出若干个数,使得这若干个数的和与M最为接近,描述一个算法,并给出算法的复杂度。
...全文
1534 51 打赏 收藏 转发到动态 举报
写回复
用AI写文章
51 条回复
切换为时间正序
请发表友善的回复…
发表回复
lifujun880912 2011-11-11
  • 打赏
  • 举报
回复
我提议用线段树
wangjj89621 2011-11-11
  • 打赏
  • 举报
回复
明显错的[Quote=引用 41 楼 huminer 的回复:]
先找到,最接近M的最大数M0,再找到最接近M-M0的最大数M1,如此继续,
[/Quote]
一名金人 2011-11-10
  • 打赏
  • 举报
回复
观摩一下先~
goldbeef 2011-11-10
  • 打赏
  • 举报
回复
很显然是0-1背包问题
Apeipo 2011-11-10
  • 打赏
  • 举报
回复
这题..别说复杂度了,让我写短时间我都写不出来- -
myhaikuotiankong 2011-11-09
  • 打赏
  • 举报
回复
[Quote=引用 40 楼 chen_wenyue 的回复:]
用最笨的遍历写了个,先供大家参考下吧:只处理了正实数,不考虑负数。如果要处理负数,可能要在堆栈判断上处理下。程序不保证一定正确,毕竟可支配时间有限,不想在这种最笨的遍历上花太多时间,有时间的朋友可以完善下。

最开始看到这道题时,是想求相临实数差,再根据遍历时,动态判断差值的范围,减少遍历的次数,但有些地方还没想明白,先留个记号,有时间再试试能不能写个优化些的算法。


C/C++ co……
[/Quote]看在写出来的份上,顶一个。。。
bullbat 2011-10-12
  • 打赏
  • 举报
回复
mark
caishenfans 2011-10-12
  • 打赏
  • 举报
回复
<编程之美>
欢乐的小猪 2011-10-11
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 nkorange 的回复:]

这题没有捷径,就是搜索+剪枝
[/Quote]


搜索+剪枝,可达到O(2N)的复杂度,且很精确,当N很大时
hzkjdxwktx 2011-10-10
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 pegaso 的回复:]
从数组从找出若干个数:这些数没强制要连续,否则到9楼就已经可以结贴了。
NP算法没有利用到有序数组,也不是最优。
可以从归纳法考虑下:

有序实数组R[N],要找其中K个数,使其和与M最接近。
K=1:二分查找,左右相邻比较一下;log(N)。
K=2:二分查找M/2的数,再分别向左右扩展,记住两数之和与M误差最小的;log(N)+N。
K=3:二分查找M/3的数,先固定一个数,再将……
[/Quote]
你固定的那个数不一定就是其中K个数之一
showjim 2011-10-09
  • 打赏
  • 举报
回复
可以考虑筛选法,先用二分法找到一个比较合适误差范围,然后不断迭代并缩小误差直到解唯一。
gmemai 2011-10-09
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 pegaso 的回复:]

从数组从找出若干个数:这些数没强制要连续,否则到9楼就已经可以结贴了。
NP算法没有利用到有序数组,也不是最优。
可以从归纳法考虑下:

有序实数组R[N],要找其中K个数,使其和与M最接近。
K=1:二分查找,左右相邻比较一下;log(N)。
K=2:二分查找M/2的数,再分别向左右扩展,记住两数之和与M误差最小的;log(N)+N。
K=3:二分查找M/3的数,先固定一个数,再……
[/Quote]
学习了
huminer 2011-10-09
  • 打赏
  • 举报
回复
先找到,最接近M的最大数M0,再找到最接近M-M0的最大数M1,如此继续,
chen_wenyue 2011-10-09
  • 打赏
  • 举报
回复
用最笨的遍历写了个,先供大家参考下吧:只处理了正实数,不考虑负数。如果要处理负数,可能要在堆栈判断上处理下。程序不保证一定正确,毕竟可支配时间有限,不想在这种最笨的遍历上花太多时间,有时间的朋友可以完善下。

最开始看到这道题时,是想求相临实数差,再根据遍历时,动态判断差值的范围,减少遍历的次数,但有些地方还没想明白,先留个记号,有时间再试试能不能写个优化些的算法。



#include <iostream>

#define IN
#define OUT
#define INOUT

int max = 10;
float in[10] = {1.1f,1.2f,1.3f,2.0f,3.2f,4.8f,9.0f,11.2f,18.0f,20.0f};
enum dState{INIT = 0, STACK};
int state[10] = {0};
float m = 28.3f;
float g_sum = 0.0f;

//float diff[10] = {0}; // 差值数组
//float d_min = 0.0f; // 最小误差

int stack[10 + 1] = {0};
int ps = 0;

void push(IN int index)
{
if( index>0 )
printf( "push:%f\n", in[index] );

ps++;
stack[ps] = index;
}

int pop()
{
int n = stack[ps--];
if(ps<0) ps = 0;

printf( "pop:%f\n", in[n] );
return n;
}

void init()
{
push(-1);
// diff[0] = m;
// for(int i= 1;i< max;i++)
// {
// diff[i] = in[i]-in[i-1];
// }
}

float getMin(IN float value, OUT int* index)
{
float tm = 0.0f;
*index = -1;
for(int i= 0;i< max;i++)
{
if(state[i] != INIT)
{
continue;
}
if( tm<in[i] && in[i]<value )
{
tm = in[i];
*index = i;
}
}
return tm;
}

int work()
{
float sum = 0.0f;
float di = 0.0f;
// a.选出最接近差值的数据
int index = -1;
float min = getMin(m, &index);
if( index< 0 ) return 0;
while(true)
{
di = m-(min+sum);
if( di< 0.1 ) // 越界
{
min = getMin(in[index], &index);
if( index <0 )
{
index = pop();
sum -= in[index];
state[index] = INIT;
}
}
else if( min< 0.1 ) // 查找空
{
index = pop();
if( index< 0 ) break;
sum -= in[index];
state[index] = INIT;
min = getMin(in[index], &index);
}
else
{
push(index);
state[index] = STACK;
sum += min;
g_sum = (sum>g_sum && m>=sum)?sum:g_sum;
printf( "di:%0.2f, min:%0.2f, sum:%0.2f, g_sum=%0.2f.\n", di, min, sum, g_sum );

min = getMin(min, &index);
}
}

return 2;
}

int main()
{
int ret = -1;
init();
ret = work();
printf("done! ret:%d, sum:%0.2f.\n", ret, g_sum );

getchar();

return 0;
}
Indifferent_Wind 2011-10-08
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 pegaso 的回复:]

从数组从找出若干个数:这些数没强制要连续,否则到9楼就已经可以结贴了。
NP算法没有利用到有序数组,也不是最优。
可以从归纳法考虑下:

有序实数组R[N],要找其中K个数,使其和与M最接近。
K=1:二分查找,左右相邻比较一下;log(N)。
K=2:二分查找M/2的数,再分别向左右扩展,记住两数之和与M误差最小的;log(N)+N。
K=3:二分查找M/3的数,先固定一个数,再……
[/Quote]
++
AndyZhang 2011-10-08
  • 打赏
  • 举报
回复
背包吧
lichanghai3166 2011-10-08
  • 打赏
  • 举报
回复
顶![Quote=引用 21 楼 pegaso 的回复:]

从数组从找出若干个数:这些数没强制要连续,否则到9楼就已经可以结贴了。
NP算法没有利用到有序数组,也不是最优。
可以从归纳法考虑下:

有序实数组R[N],要找其中K个数,使其和与M最接近。
K=1:二分查找,左右相邻比较一下;log(N)。
K=2:二分查找M/2的数,再分别向左右扩展,记住两数之和与M误差最小的;log(N)+N。
K=3:二分查找M/3的数,先固定一个数,再……
[/Quote]
lifu119 2011-10-08
  • 打赏
  • 举报
回复
学习了
「已注销」 2011-10-07
  • 打赏
  • 举报
回复
在这里,可以用到排序的作用。如果发现“从n个数中无序的取出i个数,算起和”这个和与M的差值在增大即可break本次循环。
「已注销」 2011-10-07
  • 打赏
  • 举报
回复
时间复杂度不较高的算法,但是理解起来简单:
针对"若干个数i"遍历一遍,从1到n。
然后从n个数中无序的取出i个数,算起和,与前一个比较,取小的那个即可。
加载更多回复(31)

33,017

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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