分享一道用Python基础+蒙特卡洛算法实现排列组合的题目
off999 2024-12-26 15:54 36 浏览 0 评论
来源:Python爬虫与数据挖掘
作者:Python进阶者
大家好,我是Python进阶者。这篇文章的题目真的是很难取,索性先取这个了,装个13好了。
前言
前几天在才哥交流群里,有个叫【Rick Xiang】的粉丝在Python交流群里问了一道关于排列组合的问题,初步一看觉得很简单,实际上确实是有难度的。
题目是:一个列表中有随机15个数,没有重复值。从列表里面任意选5个数,如何选出来包含a, a+1的所有组合。a可以是15个数中的任意一个。
一、思路
这个问题看似简单,思路正如上图的【张老师】说的那样,分两步走,理论上来说,确实是可以实现。正常我们计算排列组合公式,用下图中的组合公式计算是没问题的。
但是这道题目的实现,涉及到用Python程序进行实现,当然计算一个数值,对于Python和我们来说并不难,难的是需要回归排列组合原本的状态,然后用程序进行实现。本文借用了群成员【有点意思】所说的蒙特卡洛算法和代码进行实现,下面一起来看看吧!
这里引用【张老师】提及的第二种方案,先随机取14个数,然后从14个随机数中随机取一个,然后自增1,作为第15个随机数,之后再从这15个随机数中进行随机取5个随机数,再进行if判断,看看连续值是否同时存在同一个列表中,之后把满足条件的列表append到一个空列表中去,最后再去用set集合去重,得到最后的结果。
二、解决方法
1)伪代码
这里先给出【有点意思】大佬的伪代码,这样看上去大家也更加好理解一些,如下图所示。其实下面这个代码也不算是伪代码,现在Python也支持中文变量,下面这个代码也是完全可以跑起来的,只不过看上去要比下文中的纯英文代码要更加好理解一些。
下面给出具体的实现过程,这里给出5份代码,欢迎大家积极尝试。
2)代码一
# coding: utf-8
import random
def quchong(list_data):
list2 = []
for i in list_data:
if i not in list2:
list2.append(i)
return list2
# 从随机的15个数值中随机取出5个数,放到一个数组
# 生成不重复的14个随机数
random_14 = [random.randint(0, 100) for i in range(14)] # 这个写法容易出现随机值重复
random_14 = random.sample(range(100), 14)
print(random_14)
random_1 = random.choice(random_14)
random_2 = random_1 + 1
random_14.append(random_2)
random_15 = random_14
print(random_1, random_2)
final_list = []
for i in range(100):
select = [random.choice(random_15) for j in range(5)]
quchong_select = set(select)
if random_1 in quchong_select and random_2 in quchong_select:
final_list.append(quchong_select)
fina_result = quchong(final_list)
print(len(fina_result))乍一看,这个方法确实可以实现,但是这里会有一个小bug,那就是random.randint()函数生成的随机中会有重复值,而题目要求是生成不重复的随机值。那么这个问题,将在代码二中得到解决。
3)代码二
使用random.sample()函数,这个函数可以随机产生随机值,而且不会重复,还是很奈斯的。另外,使用了numpy.random.choice()函数,可以直接选择随机的5个数,效率比代码一更高一些。
# -*- coding: utf-8 -*-
import numpy as np
import random
def quchong(list_data):
list2 = []
for i in list_data:
if i not in list2:
list2.append(i)
return list2
# 从随机的15个数值中随机取出5个数,放到一个数组
# 生成不重复的14个随机数
random_14 = random.sample(range(100), 14)
print(random_14)
random_1 = random.choice(random_14)
random_2 = random_1 + 1
random_14.append(random_2)
random_15 = random_14
print(random_1, random_2)
final_list = []
for i in range(100):
sub_random_data = np.random.choice(random_15, 5)
quchong_select = set(sub_random_data)
if random_1 in quchong_select and random_2 in quchong_select:
final_list.append(quchong_select)
fina_result = quchong(final_list)
print(len(fina_result))4)代码三
代码三主要是在代码一和代码二的基础上加了一些函数,使得读起来更加的有逻辑性和层次感。
# -*- coding: utf-8 -*-
# 模块化
import random
import numpy as np
# 从随机的15个数值中随机取出5个数,放到一个数组,生成不重复的14个随机数
def get_random15():
random_14 = random.sample(range(1000), 14)
print(random_14)
random_1 = random.choice(random_14)
random_2 = random_1 + 1
random_14.append(random_2)
random_15 = random_14
print(random_1, random_2)
get_final_result(random_1, random_2, random_15)
def get_final_result(random_1, random_2, random_15):
final_list = []
for i in range(1000):
sub_random_data = np.random.choice(random_15, 5)
quchong_select = set(sub_random_data)
if random_1 in quchong_select and random_2 in quchong_select:
final_list.append(quchong_select)
fina_result = quchong(final_list)
print(len(fina_result))
def quchong(list_data):
list2 = []
for i in list_data:
if i not in list2:
list2.append(i)
return list2
if __name__ == '__main__':
get_random15()5)代码四
细心的朋友可能已经发现了一个问题,在随机从np.random.choice(random_15, 5)取值的时候,也会取出重复的值,这样也是不符合要求的,这里给出了一个方案,从15个随机数中取出一个之后,然后remove掉这个取出的数,重新去剩下的列表中去取,这样就完美的避开了这个问题。
# 模块化
import random
import numpy as np
# 取出随机的15个数值
def get_random15():
for i in range(2):
random_15 = random.sample(range(20), 15)
# print(random_15)
get_random5(random_15)
# 遍历随机的15个数值,取相邻的两个随机数,并调用函数进行处理
def get_random5(random_15):
random_5 = []
# 遍历5次,从random_15中取5个不同的元素
for i in range(5):
random_data = np.random.choice(random_15)
random_5.append(random_data)
random_15.remove(random_data)
# print(random_5)
for num in random_5:
random_1 = num
random_2 = random_1 + 1
get_final_result(random_1, random_2, random_5)
# 判断相邻的两数值是否同时存在随机的15个数值的列表中,如果满足要求,就存到一个列表中,并调用去重函数
def get_final_result(random_1, random_2, random_5):
final_list = []
if random_1 in random_5 and random_2 in random_5:
print(random_5)
final_list.append(random_1)
result = quchong(final_list)
print(result)
# 针对得到的所有列表,进行去重处理
def quchong(list_data):
list = []
for i in list_data:
if i not in list:
list.append(i)
return list
if __name__ == '__main__':
get_random15()代码写到这里,已经比之前的方案要好很多了,比之前的三个代码都要严谨一些,但是仍然存在不足。虽然解决了随机生成重复性的问题,也解决了随机从random_15中取出重复数的问题,但是弊端还是存在的。这个代码遍历挺多的,复杂度倒是正常,但是输出的格式不太好看,没有达到预期。这里我只是遍历了2次,而且随机数我只是开放到0-20,如果循环次数增多,数值越多的话,计算起来速度可就不好说了。
6)代码五
经过【有点意思】大佬和我的共同努力,现在祭出终极版本,这个版本是迄今为止,针对该问题写出的最严谨的一个版本了,代码如下。
# -*- coding: utf-8 -*-
# 模块化
import random
import numpy as np
import time
# 取出随机的15个数值
def get_random15():
for i in range(100000):
random_15 = random.sample(range(2000), 15)
# print("随机15数=",random_15,len(random_15))
get_random5(random_15)
# 遍历随机的15个数值,取相邻的两个随机数,并调用函数进行处理
def get_random5(random_15):
random_5 = []
# 遍历5次,从random_15中取5个不同的元素
for i in range(5):
random_data = np.random.choice(random_15)
random_5.append(random_data)
random_15.remove(random_data)
# print("random_5=",random_5)
# print("random_15=",random_15)
for num in random_5:
random_1 = num
random_2 = random_1 + 1
# print(random_1,random_2)
get_final_result(random_1, random_2, random_5)
# 判断相邻的两数值是否同时存在随机的15个数值的列表中,如果满足要求,就存到一个列表中,并调用去重函数
def get_final_result(random_1, random_2, random_5):
final_list = []
if random_1 in random_5 and random_2 in random_5:
# print(random_5)
final_list.append(random_5)
result = quchong(final_list)
if result:
if len(result[0]) == 5:
# print(random_1,random_2)
# print("result=",result)
final_result.append(result)
# 针对得到的所有列表,进行去重处理
def quchong(list_data):
list = []
for i in list_data:
if i not in list:
list.append(i)
return list
if __name__ == '__main__':
start_time = time.time()
global final_result
final_result = []
get_random15()
final_result = quchong(final_result)
print("共%d个符合题意的列表" % len(final_result))
print("分别是:%s" % final_result)
end_time = time.time()
used_time = end_time - start_time
print()
print("本次程序用时:{}".format(time.strftime('%H(小时):%M(分钟):%S(秒)', time.gmtime(used_time))))这个代码运行之后,可以看到符合题意列表的具体个数,还有具体的列表数值,还有耗时时间。
经过测试,在10万次循环以内,符合要求的数据大概有1000左右,运行时间也只是秒级的。如果继续扩大循环力度,程序的复杂度会更加大,更加贴近理论的排列组合值,因为耗时太长,这里不再做测试,感兴趣的话,自己可以改下参数进行调试。
三、总结
我是Python进阶者。本文基于粉丝针对排列组合问题的提问,给出了一个利用Python基础+蒙特卡洛算法的解决方案,基本上可以达到了粉丝的要求。
不过话说回来,这个方案还是存在一定的弊端的,随着循环次数越多,随机数越大,排列组合数就会越多,运行的时间也就会越长,当然得到的数据也就更加的精准了。
最后感谢【Rick Xiang】提问,感谢【张老师】提供的思路,感谢【有点意思】大佬一直和我探讨交流学习,这一过程,虽然耗时,但是也是学到了很多知识,也感谢我寄几花时间和经历整理这篇接近4000字的文章。
针对这个问题,小编这里整理了1个思路,当然实现方法肯定远远不只是这1种,如果你有其他的方法,可以随时分享给我噢!
小伙伴们,快快实践一下吧!
相关推荐
- 怎么用火绒关闭win安全中心(win10火绒安全软件怎么关闭)
-
一、火绒防火墙关闭方法在电脑上运行火绒软件后,点击首页界面的“防护中心”,在病毒防护界面可以关闭文件、U盘、邮件等保护功能,。系统防护:在该界面可以关闭系统防护功能,。网络防护:可以关闭网络保护等功...
- 微软应用商店下载手机版(微软应用商店在哪下)
-
、在桌面任务栏找到微软应用商店,点击并打开。2、进入页面后点击【应用】,进入应用页面。3、在页面里往下移动,找到热门应用,找到一个软件,点击进入。4、进入页面后,点击【安装】,软件会自动安装,安装完毕...
- win11系统怎么查看电脑配置(win11怎么查看系统版本)
-
答:win11查看电脑配置步骤如下。1.点击下方任务栏的windows图标或者按下键盘“windows键”打开开始菜单。2.在开始菜单中找到“设置”或“settings”,一般是右上角的齿轮状按钮,3...
- 麦克风没坏但是没声音(麦克风没声怎么回事)
-
几种可能性,供您参考:1、麦是完全好的(其它机子上可以用)2、插孔没有插错3、音量控制里的麦克风并没有静音掉4、声卡驱动已重装过N次,新的旧的都试过了5、音量控制→属性→录音→麦克风下面的勾...
- wps office是干什么的(wps office是干什么的可以卸载吗)
-
WPSOffice一站式办公服务平台,具有可兼容Word、Excel、PPT三大办公组件的不同格式,支持PDF文档的编辑与格式转换集成思维导图、流程图等诸多功...
- 百度网页(百度网页自动翻译怎么设置)
-
1、百度的新闻源网站太多了,基本上大型的商业门户+政府官方的媒体、机构部门都是。2、出现在【百度新闻】里的网站都是新闻源网站。3、怎么判断一个网站是不是新闻源:1)在百度新闻下直接搜网站名字,如果出现...
- 外国网站的浏览器下载(外国网站的浏览器下载Games)
-
答,可在浏览器上面下载所需要的视频/音乐的名称,下载完毕后,按所给的排列表找出所需要的视频/音乐。如果是喜欢的视频/音乐它在浏览器里边都有分类,可详细的介绍一下自己吧,还可以在古典音乐或者名著导读介绍...
-
- 京东攒机助手(京东攒机在哪)
-
自己在京东买的配置,以为身边的人能帮忙组装,但是好像超过了个人的认知,所以无奈之下只能在京东找专业人士进行安装,挺快,前一天傍晚下单,第二天上午上班就来了,组装师傅挺好,挺有耐心,业务也挺熟练,走线看起来也不错,买的机箱是师傅从来没有接触过...
-
2025-11-14 22:03 off999
- 腾讯电脑管家和360哪个好(腾讯电脑管家好用还是360好用)
-
两个都很好。1.腾讯电脑管家和360卫士都是电脑上最常见的免费杀毒软件,两款软件在病毒查杀上都是首屈一指的。2.360卫士在功能上十分丰富,从木马查杀到电脑清理以及优化加速都是一应俱全的,而且还集成了...
- 笔记本突然没声音(笔记本突然没声音是什么原因)
-
可能是因为电脑声音驱动设备故障导致电脑没有声音。解决方法:使用Win+X快捷键,然后在弹出的窗口中点击“设备管理器”选项,之后点击“打开声音、视频和游戏控制器”选项,打开的属性界面查看运行是否正常,或...
- 大白菜一键装机win7系统(大白菜装系统教程win7)
-
1.电脑开机按f2或del进bios里面,启动项里面设置U盘启动,保存退出重启。2.键盘上一直按f12或f10,选择大白菜的u盘,进入pe界面,键盘按上下健移动,选择2003pe或win10pe,按回...
- 电脑windows密钥怎么查(windows密钥怎么看)
-
Win10系统查看并激活产品密钥的方法为:1、首先、进入到电脑屏幕的首页,在左上角会看到界面首页的“此电脑”选项。2、右键单次点击“此电脑”选项,在弹出的菜单快捷栏中选择最下方的“性”选项,并进行点击...
- 深度技术ghost xp sp3 如何安装
-
1、ghostxpsp3快速装机版使用ghost镜像来安装。方便快捷易操作。2、电脑开机进入bios后设置成光驱启动。设置方法参阅主板说明书。3、放入安装光盘后保存退出。电脑自动重启后光盘开始引导...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
慕ke 前端工程师2024「完整」
-
失业程序员复习python笔记——条件与循环
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
