生成n个长度1~r的唯一随机排列的Python实现性能优化问题
问题原因
你的代码卡在n>=18300的核心原因是拒绝采样的冲突率随已生成序列占比提升呈指数级上升:当已经生成18200个唯一序列后,后续随机生成的序列有极大概率已经在去重集合中,程序会陷入反复生成重复序列、反复校验去重的死循环,几乎无法推进到目标数量。
此外你用''.join(perm)作为去重哈希键存在隐藏bug:如果数组元素是多字符字符串,不同序列可能拼接出完全相同的字符串,导致误判重复。
优化方案
你可以采用「唯一ID映射+无重复采样」的思路重写函数,完全避免重复生成的问题,性能可以提升两个数量级:
import random from typing import List def get_permutations(arr: List[str], n: int, r: int) -> List[List[str]]: arr_len = len(arr) # 预计算不同长度序列的ID起始偏移量 offset_list = [0] for k in range(1, r + 1): offset_list.append(offset_list[-1] + arr_len ** k) total_available = offset_list[-1] if n > total_available: raise ValueError(f"最多可生成{total_available}个唯一序列,请求的n={n}超出上限") # 直接抽取n个不重复的随机ID,对应每个唯一序列 selected_ids = random.sample(range(total_available), n) result = [] for seq_id in selected_ids: # 确定当前序列的长度 seq_len = 0 for k in range(1, r + 1): if seq_id < offset_list[k]: seq_len = k seq_id -= offset_list[k - 1] break # 将ID转换为对应长度的序列 current_seq = [] for _ in range(seq_len): current_seq.append(arr[seq_id % arr_len]) seq_id = seq_id // arr_len # 无需保持顺序的话可以去掉下面这行反转,性能更高 current_seq = current_seq[::-1] result.append(current_seq) return result
方案优势
- 性能稳定:不需要循环去重,时间复杂度稳定为
O(n*r),你的场景下生成20000个序列耗时低于100ms。 - 无冲突风险:用唯一整数ID映射序列,完全规避了字符串拼接的哈希冲突bug。
- 鲁棒性更强:如果请求的序列数量超过理论上限,会直接抛出明确错误,避免无意义的死循环。
内容的提问来源于stack exchange,提问作者emremrah
相关产品推荐
相关产品推荐

