求助:生成含A、B、C、D各15次且无连续重复的随机列表
问题根源
你的代码只做了一次半吊子检查:发现一处连续重复后,重新打乱列表就直接终止检查了,根本没去验证新打乱的列表是不是还有连续重复,所以返回的结果自然大概率不符合要求。
修复方案1:循环验证到合格为止
既然想用打乱的思路,就得死磕到生成完全符合要求的列表:
import random def create_random_list(): letters = ['A', 'B', 'C', 'D'] freq = 15 total = len(letters) * freq while True: # 生成初始重复列表并打乱 lst = sum([[letter]*freq for letter in letters], []) random.shuffle(lst) # 遍历检查所有相邻元素 valid = True for i in range(1, total): if lst[i] == lst[i-1]: valid = False break # 没问题就返回 if valid: return lst print(create_random_list())
这个方法逻辑简单,虽然极端情况可能要多打乱几次,但60个元素的列表实际跑起来速度很快,完全不用担心效率。
修复方案2:直接构造更高效
反复打乱有点碰运气,不如直接一步步构造符合要求的序列。核心思路是:每次选不是上一个字母的选项,并且优先选剩余数量多的,避免某类字母用完后卡壳:
import random from collections import defaultdict def create_random_list(): letter_counts = {'A':15, 'B':15, 'C':15, 'D':15} result = [] last = None for _ in range(60): # 筛选出可选的字母:不是上一个且还有剩余 options = [k for k, v in letter_counts.items() if v>0 and k != last] # 优先挑剩余多的,防止卡壳;数量相同就随机选 max_left = max(letter_counts[opt] for opt in options) candidates = [opt for opt in options if letter_counts[opt] == max_left] chosen = random.choice(candidates) result.append(chosen) letter_counts[chosen] -= 1 last = chosen return result print(create_random_list())
这种方法一次就能生成合格序列,随机性也足够,比反复打乱靠谱多了。
再啰嗦下原代码的问题
原代码里,只要找到一处连续重复,打乱后就直接break了检查循环,根本没去看新列表是不是还有重复。比如第一次打乱有5处重复,代码只看到第一处就打乱,新列表可能还有3处重复,但直接返回了,结果当然不合格。
内容的提问来源于stack exchange,提问作者Pablo Blanco
相关产品推荐
相关产品推荐

