鱼C论坛

 找回密码
 立即注册
查看: 5332|回复: 21

[技术交流] Python: 每日一题 55

[复制链接]
发表于 2017-5-26 15:09:39 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 ooxx7788 于 2017-5-26 16:56 编辑

马上要放假了,今日再来一题。Sixpy说题目越来越简单,那就出个难点的(4kyu)。

  1. 有一个数列u,使得u符合以下规则:
  2. 1、u的第一个数字是1.
  3. 2、对于u中的每一个x,都有y=2*x+1 和z=3*x+1,且y和z都在u中。
  4. 3、u中没有其他数字。
复制代码

例如:
  1. u = [1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, ...]
复制代码


1  --->  y(1) = 3  ,z(1) = 4
3  --->  y(3) = 7  ,z(3) = 10
4  --->  y(4) = 9  ,z(4) = 13
....

要求:给出函数dbl_linear(n),  返回按顺序排列的u[n]。
例如: dlb_linear(10) 返回  22.
注意:请考虑效率问题(1<n<100000)

jerry已经把答案做出来了,我就先把答案放出来吧。我自己写的答案在6楼,这里提供的是一个网络上面比较高效的答案。
游客,如果您要查看本帖隐藏内容请回复

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-5-26 16:11:05 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-5-26 16:12 编辑

感觉效率可能是问题
  1. def dbl_linear(n):
  2.     def addin(num):
  3.         if num not in s:
  4.             u.append(num)
  5.             s.add(num)
  6.     u = [1, 3, 4]
  7.     s = set(u)
  8.     i = 1
  9.     while len(s) < n * 1.2:
  10.         addin(u[i] * 2 + 1)
  11.         addin(u[i] * 3 + 1)
  12.         u.sort()
  13.         i += 1
  14.     return u[n]

  15. print(dbl_linear(10000))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-26 16:32:24 | 显示全部楼层
不用排序的方法,改插入法,时间可以缩短一半
  1. def dbl_linear(n):
  2.     def addin(num):
  3.         if num not in s:
  4.             s.add(num)
  5.             for i in range(len(u) - 1, 0, -1):
  6.                 if u[i] < num:
  7.                     u.insert(i + 1, num)
  8.                     return

  9.     u = [1, 3, 4]
  10.     s = set(u)
  11.     i = 1
  12.     while len(s) < n * 1.2:
  13.         addin(u[i] * 2 + 1)
  14.         addin(u[i] * 3 + 1)
  15.         i += 1
  16.     return u[n]

  17. print(dbl_linear(10000))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-26 16:33:29 | 显示全部楼层
jerryxjr1220 发表于 2017-5-26 16:11
感觉效率可能是问题

效率确实低了,我电脑上面n = 100000时候,用了84秒。我的只跑了1.8秒。
而且结果还有个问题,算n=100000 和n=10000结果都对,但是算n=20时候,结果应该是57,你的计算结果是58.  n的倍数要调大一些结果才对。但是n的结果调大了,函数的计算效率就更低了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-26 16:45:19 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-5-26 16:50 编辑
ooxx7788 发表于 2017-5-26 16:33
效率确实低了,我电脑上面n = 100000时候,用了84秒。我的只跑了1.8秒。
而且结果还有个问题,算n=10000 ...


要么就是死命加倍数,反正只要倍数足够大,总归可以涵盖的。。。
  1. def dbl_linear(n):
  2.     def addin(num):
  3.         if num not in s:
  4.             s.add(num)
  5.             u.append(num)

  6.     u = [1, 3, 4]
  7.     s = set(u)
  8.     i = 1
  9.     while len(s) < n * 10:
  10.         addin(u[i] * 2 + 1)
  11.         addin(u[i] * 3 + 1)
  12.         i += 1
  13.     u.sort()
  14.     return u[n]

  15. print(dbl_linear(100000))
复制代码

这样1秒就可以出答案了。。。
2911582
[Finished in 1.2s]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-26 16:53:46 | 显示全部楼层
jerryxjr1220 发表于 2017-5-26 16:45
要么就是死命加倍数,反正只要倍数足够大,总归可以涵盖的。。。

这样1秒就可以出答案了。。。

其实根本不需要addin和set的部分。

例如,我就是这样写的。原题里面更新一个用双端队列模块写的,效率比我写的高可能有10倍。
  1. def dbl_linear(n):
  2.     u = [1]
  3.     i = 0
  4.     while len(u) < n * 10:
  5.         u.append(u[i] * 2 + 1)
  6.         u.append(u[i] * 3 + 1)
  7.         i += 1
  8.     return sorted(list(set(u)))[n]
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-5-26 17:02:55 | 显示全部楼层
ooxx7788 发表于 2017-5-26 16:53
其实根本不需要addin和set的部分。

例如,我就是这样写的。原题里面更新一个用双端队列模块写的,效率 ...

嗯,我这2个函数是根据原来的思路改过来的,如果是单纯的只要加大n的倍数的话,确实不需要addin和set部分了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-7-17 21:12:10 | 显示全部楼层
两个函数,题目没说重复的元素怎么算?假设重复的也算在列表里面
关键应该是知道什么时候停止

把这个按照二叉树画出来,发现这玩意就是堆排序的最小堆
那要得n个数,就要 m =logn(2为底数),取顶函数,得到层数 m
如果在第 k 层的最左分支比第 m 层最右分支大,就可以停止了
  1. # 用列表
  2. def dbl_linear(n):
  3.     s = [1]
  4.     m = math.ceil(math.log(n,2))
  5.     i,j,max_num,min_num =0,0,1,1
  6.     while i<m:
  7.         max_num = 3*max_num+1
  8.         i +=1
  9.     while min_num < max_num:
  10.         min_num = 2*min_num+1
  11.         j +=1
  12.         
  13.     for k in range(2**j):
  14.         s.extend([2*s[k]+1,3*s[k]+1])
  15.         if len(s)>=2**j:
  16.             break
  17.     s = sorted(s)
  18.     return s[n]
复制代码

换一种问法,就是找到我没排序之前的第 n 个数 s[n],找出所有比它小的数
最左分支是一路 2*x+1 下来,每一层最小一定是最左,这个数比 s[n]小,则后面排除
  1. def dbl_linear2(n):
  2.     s = [1]
  3.     m = 1
  4.     for i in range(n):
  5.         s.extend([2*s[i]+1,3*s[i]+1])
  6.     while m<s[n]:
  7.         m = 2*m +1
  8.     for j in range(n,m):
  9.         s.extend([2*s[j]+1,3*s[j]+1])
  10.         if 2*s[i]+1==m:
  11.             break
  12.     s = sorted(s)
  13.     return s[n]
复制代码

如果重复的不算,那结果就先用set()过一遍,再索引
最终耗时,n=100000时, 4.7s,有点慢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-2-10 17:20:18 | 显示全部楼层
本帖最后由 kwty 于 2018-2-10 17:24 编辑

from time import clock
clock()
list1 = [1]
n = 100000
c = list1
while len(list1) < n + 1:
        L1 = [2 * i + 1 for i in c]
        L2 = [3 * i + 1 for i in c]
        c = []
        c.extend(L1)
        c.extend(L2)
        list1.extend(L1)
        list1.extend(L2)
        list1 = list(set(list1))
list1.sort()

print(list1[n],clock())


4487787 0.17909268667594722
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-2-11 13:35:13 | 显示全部楼层
自己想不出来
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-7-23 20:38:44 | 显示全部楼层
学习一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-18 13:21:52 | 显示全部楼层
看看答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-1 10:31:28 | 显示全部楼层
看答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-1 16:12:48 | 显示全部楼层
答案呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-2 22:53:59 From FishC Mobile | 显示全部楼层
看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-6-24 18:36:08 | 显示全部楼层
1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-7-28 21:22:59 | 显示全部楼层
sorted(list(set(u)))[n] 是参考楼主的
自己的for循环比楼主的while循环快一丢丢,嘻嘻

  1. # 自己的代码
  2. def dlb_linear(n):
  3.     u = [1]
  4.     for i in range(n * 5):
  5.         u.append(u[i] * 2 + 1)
  6.         u.append(u[i] * 3 + 1)
  7.     print(sorted(list(set(u)))[n])

  8. # 楼主的代码
  9. def dbl_linear(n):
  10.     u = [1]
  11.     i = 0
  12.     while len(u) < n * 10:
  13.         u.append(u[i] * 2 + 1)
  14.         u.append(u[i] * 3 + 1)
  15.         i += 1
  16.     print(sorted(list(set(u)))[n])
复制代码

  1. 本机测试 n = 100000 时
  2. 2911582
  3. 用时: 0.7678713798522949
  4. 2911582
  5. 用时: 0.8851046562194824
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-28 21:36:46 | 显示全部楼层
本机测试了 n = 1000000 时的结果
自己的答案和楼主的答案一致,跟隐藏的代码答案不一致,结果是隐藏的代码答案正确。。。
用时少答案还准确,太厉害了

  1. # 自己的
  2. 54383518
  3. 用时: 7.671760559082031
  4. # 楼主的
  5. 54383518
  6. 用时: 8.959300994873047
  7. # 隐藏的
  8. 54381286
  9. 用时: 1.1793506145477295
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-9-20 21:19:59 | 显示全部楼层
def dlb_linear(n):
    list_z = [1]
    i = 0
    while len(list_z)<=n:
        list_z.append(2*list_z[i]+1)
        list_z.append(3*list_z[i]+1)
        i+=1
    # list_reulst = list_z.sort()
    list_reulst = sorted(list_z)
    return list_reulst[n]

print(dlb_linear(10))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-9-20 23:21:43 | 显示全部楼层
学习了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-12 21:33

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表