一道juniper的面试题,算法求改进,求时间复杂度~

wlcw16 2012-12-29 08:55:41
题目来源自http://bbs.csdn.net/topics/390315847 #32楼

题目要求:
定义一个数字有以下的特征, 它可以被分成几个部分,而前面的部分相加起来的和是后面的部分.举例来说
1235813, 1+2=3; 2+3=5;3+5=8; 5+8=13;
112112224, 112+112=224;
1981100, 19+81=100;
122436, 12+24=36;
1299111210, 12+99=111,99+111=210;
要求写出一个函数,输入一个数字,判断这个数字是不是要求的这个数。


说者无意听者有心啊
http://blog.csdn.net/wlcw16/article/details/8303104
我自己写了个算法,但是感觉应该还会有简化的空间。

并且求大神帮忙算下时间复杂度,如果数的位数为n的话。
...全文
375 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
geansea 2013-01-01
  • 打赏
  • 举报
回复
0开头简单特殊处理下就行了,关键还是前两个数。
wlcw16 2013-01-01
  • 打赏
  • 举报
回复
算法还是很差,后面各位还没有考虑到0开头的情况。。
geansea 2012-12-31
  • 打赏
  • 举报
回复
一点想法: 姑且规定这串数字不以0开头,分割后每段也不以0开头。 那么,前两个分割位就唯一确定了整个的分割方法(如果这分割方法存在的话)。 换句话说,只要知道了前两个分割出来的数,后面第三、四、五……个分别应该是什么就都知道了。 所以要遍历的是前两个分割位置,确定一组分割位置之后,只需要简单的数字比较。 O(n^2)就可以了。 然后还可以通过一些方法快速判断,比如位数、个位数字什么的。
FancyMouse 2012-12-30
  • 打赏
  • 举报
回复
嗯允许开头0的话稍微处理一下就可以了,三次方还是三次方
FancyMouse 2012-12-30
  • 打赏
  • 举报
回复
不对……允许数字零开头的话这题就远不是三次方那么简单了……
FancyMouse 2012-12-30
  • 打赏
  • 举报
回复
引用 2 楼 panghuhu250 的回复:
这样看一个数:d1 s1 d2 s2 d3 s3 ... dn sn,其中di是数字,si是可能分割的位置。 取定a1,a2后,要验证a1,a2开头的序列是否满足条件最坏的情况需要lgn次加法,以及n次位数比较。但我想平均下来应该为O(1),因为几乎所有的情况都会在第一次加法时就可以淘汰了。 a1,a2的取法有n(n-1)/2种,因为要从si中取两个。 ……
字符串是全零最后一个才是1,这个无论哪个a1 a2都要判到最后才能判出来。所以最坏三次方没错。 当然比三次方快的我也不会。
panghuhu250 2012-12-30
  • 打赏
  • 举报
回复
引用 2 楼 panghuhu250 的回复:
取定a1,a2后,要验证a1,a2开头的序列是否满足条件最坏的情况需要lgn次加法。 ……
lgn不对,应为O(n).
panghuhu250 2012-12-30
  • 打赏
  • 举报
回复
这样看一个数:d1 s1 d2 s2 d3 s3 ... dn sn,其中di是数字,si是可能分割的位置。 取定a1,a2后,要验证a1,a2开头的序列是否满足条件最坏的情况需要lgn次加法,以及n次位数比较。但我想平均下来应该为O(1),因为几乎所有的情况都会在第一次加法时就可以淘汰了。 a1,a2的取法有n(n-1)/2种,因为要从si中取两个。 所以时间复杂度为O(n^3)(或O(n^2)).
In [106]: def isLegal(n, i, j):
     ...:     """取前i位为a1,第i+1到j位为a2,检测n是否由a1和a2生成的序列组成。"""
     ...:     nextDigit = j
     ...:     a1 = int(n[:i])
     ...:     a2 = int(n[i:j])
     ...:     while nextDigit<len(n): # n还有数字可用
     ...:         a2, a1 = a1+a2, a2
     ...:         s2 = str(a2)
     ...:         if n.startswith(s2, nextDigit): #从n的第nextDigit位开始,与s2比较
     ...:             nextDigit += len(s2)
     ...:         else:
     ...:             return False
     ...:     return True

In [107]: def test(n):
     ...:     for i in range(1, len(n)-1):
     ...:         for j in range(i+1, len(n)-1):
     ...:             if isLegal(n, i, j):
     ...:                 return True
     ...:     return False

In [108]: test('1235814')
Out[108]: False

In [109]: test('1235813')
Out[109]: True

In [110]: test('112112224')
Out[110]: True

In [111]: test('1299111210')
Out[111]: True
FancyMouse 2012-12-30
  • 打赏
  • 举报
回复
你这算法根本就是错的。10111,可以分成10+1=11,你输出false。
wlcw16 2012-12-30
  • 打赏
  • 举报
回复
引用 1 楼 FancyMouse 的回复:
你这算法根本就是错的。10111,可以分成10+1=11,你输出false。
如果是这种思路的话,需要改进我的算法,外层大循环不已步长来进行循环, 通过对a1a2的初始化来进行循环判断,后面的判断算法应该不需要动。
wlcw16 2012-12-30
  • 打赏
  • 举报
回复
引用 1 楼 FancyMouse 的回复:
你这算法根本就是错的。10111,可以分成10+1=11,你输出false。
因为题目不全,我看的举例来说,初始的加数的位数都是相同的。

33,027

社区成员

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

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