使用NumPy生成1到n区间所有幸运数字的实现方案咨询
幸运数字生成规则
幸运数字生成流程如下:
- 初始生成1到n的连续整数序列,例如n=32时初始序列为:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 - 第一轮移除所有排位为2的倍数的元素,得到序列:
1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31 - 取1之后的第一个幸存元素3作为步长,移除当前序列中所有排位为3的倍数的元素
- 再取3之后的第一个幸存元素7作为新步长,移除当前序列中所有排位为7的倍数的元素
- 重复上述逻辑:每次取当前步长对应位置之后的下一个幸存数作为新步长,移除排位为新步长倍数的元素,直到步长大于当前序列总长度时停止迭代,最终剩余的元素就是幸运数字。n=32时最终得到的幸运数字为:
1,3,7,9,13,15,21,25,31
现有代码问题分析
你编写的代码存在两个核心错误,是导致运行结果不符合预期、无法适配大规模场景的根本原因:
import numpy as np a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]) b = a[::2] #using skip of 2 on our array c = b[::3] #using skip of 3 on our array d = c[::7] #using skip of 7 on our array e = d[::9] #using skip of 9 on our array print(e)
- 切片逻辑完全错误:NumPy中
arr[::step]的规则是从起始位置开始,每隔step个位置取一个元素。以步长3为例,该写法只会保留排位为1、4、7…的元素,但实际规则要求仅移除排位为3、6、9…的元素,其余排位元素都需要保留,多轮错误切片后自然只会剩下首个元素1。 - 硬编码步长不具备通用性:手动指定步长既不能适配任意n值的计算需求,面对1000亿级别的超大规模范围时,手动枚举步长更是完全不现实。
自动迭代的高效NumPy实现
下面的实现通过自动迭代更新步长、布尔掩码过滤的方式实现逻辑,第一轮直接生成奇数序列可以直接节省一半内存,配合NumPy向量化运算可以支撑大规模数值计算:
import numpy as np def get_lucky_numbers(n: int) -> np.ndarray: if n < 1: return np.array([], dtype=np.int64) # 第一轮直接生成奇数序列,跳过步长2的过滤流程,直接减少一半内存占用 arr = np.arange(1, n + 1, 2, dtype=np.int64) # 步长指针从索引1开始,对应第一个有效步长3 step_ptr = 1 while True: current_step = arr[step_ptr] # 步长超过当前序列长度时停止迭代 if current_step > len(arr): break # 生成布尔掩码:保留所有排位不是当前步长倍数的元素(索引从0开始,排位=索引+1) mask = (np.arange(len(arr)) + 1) % current_step != 0 arr = arr[mask] # 指针后移,取下一个幸存元素作为新步长 step_ptr += 1 return arr # 测试n=32的场景,输出和规则结果完全一致 if __name__ == "__main__": print(get_lucky_numbers(32)) # 输出: [ 1 3 7 9 13 15 21 25 31]
- 性能说明:对于n=1000亿的场景,第一轮过滤后数组长度仅为500亿,后续每轮迭代数组长度会快速衰减,整体内存占用可控。如果需要进一步压榨超大规模场景的计算性能,可以配合Numba JIT编译、分块计算的方式优化,速度还能提升数倍。
内容的提问来源于stack exchange,提问作者Desmild
相关产品推荐
相关产品推荐

