我想要得到长度为n的任何范围的所有排列,从0开始,到n(range(n))结束,并且没有连续的数字.

示例:[0,1,2,3,4]

在那里,排列应该看起来像[0,2,4,1,3][3,1,4,2,0]

我目前的方法只获取所有现有的排列,并跳过其中包含连续数字的排列:

import itertools
all = itertools.permutations(range(n))
  
for e in all:
  double = True
      
  for a, b in zip(e, e[1:]):
    if abs(int(a)-int(b)) <= 1:
      double = False
      break

    if double == True:
      # do sth

我对这个代码的问题是,排列的数量增加得非常快,当范围达到10或更大时,我大部分时间只是跳过排列和腰部时间.有什么方法可以更有效地做到这一点吗?

另一个问题是:如果这可以更快地完成,那么是否也有更省时的实现,其中元素必须至少分开2个单元?将第if abs(int(a)-int(b)) <= 1行更改为if abs(int(a)-int(b)) <= 2,并且只接受像[0,4,1,5,2,6,3]这样的排列?

推荐答案

下面的递归函数可以做到这一点.它只构造想要的排列.它接受dst参数,该参数指示从集合rem到列表beg的末尾的下一个加法必须是exceeded的最小距离.

# comp_perm: complete the permutation
# beg: beginning of sequence
# rem: set of remaining (still unused) numbers
# dst: integer indicating distance that must be *exceeded*
def comp_perm(beg: list, rem: set, dst: int) -> list:
  if (not rem): # check whether rem is the empty set
    return [beg]
  return_lst = [] # list of sequences starting with beg
  for num in rem:
    if (not beg) or abs(num - beg[-1]) > dst:
      return_lst.extend(comp_perm(beg+[num], rem-{num}, dst))
  return return_lst

comp_perm([], set(range(5)), 1)
# [[0, 2, 4, 1, 3], [0, 3, 1, 4, 2], [1, 3, 0, 2, 4], ...]

For循环判断每个可能的加法numbeg的最后一个元素之间的距离是否为bigger than dst.如果beg是空列表(not beg),则不需要这样的判断.

以下是它的全部通用用法:

comp_perm([5, 9], {7, 11, 100}, 3)
# [[5, 9, 100, 11, 7], [5, 9, 100, 7, 11]]

叫唤

for tpl in comp_perm([], set(range(5)), 1):
  print(tpl)

打印以下内容:

[0, 2, 4, 1, 3]
[0, 3, 1, 4, 2]
[1, 3, 0, 2, 4]
[1, 3, 0, 4, 2]
[1, 4, 2, 0, 3]
[2, 0, 3, 1, 4]
[2, 0, 4, 1, 3]
[2, 4, 0, 3, 1]
[2, 4, 1, 3, 0]
[3, 0, 2, 4, 1]
[3, 1, 4, 0, 2]
[3, 1, 4, 2, 0]
[4, 1, 3, 0, 2]
[4, 2, 0, 3, 1]

叫唤

for tpl in comp_perm([], set(range(6)), 2):
  print(tpl)

打印以下内容:

[2, 5, 1, 4, 0, 3]
[3, 0, 4, 1, 5, 2]

您需要的示例[0,4,1,5,2,6,3]位于7个数字的结果中,其中dst设置为2:

[0,4,1,5,2,6,3] in comp_perm([], set(range(7)), 2)
# True

扩大要置换的数字集很快就会导致长长的列表:

len(comp_perm([], set(range(5)), 2))
# 0
len(comp_perm([], set(range(6)), 2))
# 2
len(comp_perm([], set(range(7)), 2))
# 32
len(comp_perm([], set(range(8)), 2))
# 368

len(comp_perm([], set(range(7)), 3))
# 0
len(comp_perm([], set(range(8)), 3))
# 2
len(comp_perm([], set(range(9)), 3))
# 72
len(comp_perm([], set(range(10)), 3))
# 1496

顺便说一句,answer by Andrej Kesely人很好地利用了yield.

Python相关问答推荐

Django:如何将一个模型的唯一实例创建为另一个模型中的字段

从包含基本数据描述的文本字段中识别和检索特定字符序列

Pandas read_jsonfuture 警告:解析字符串时,to_datetime与单位的行为已被反对

如何使用bs 4从元素中提取文本

过滤绕轴旋转的螺旋桨

如何让我的Tkinter应用程序适合整个窗口,无论大小如何?

Class_weight参数不影响RandomForestClassifier不平衡数据集中的结果

线性模型PanelOLS和statmodels OLS之间的区别

Pytest两个具有无限循环和await命令的Deliverc函数

为什么默认情况下所有Python类都是可调用的?

组/群集按字符串中的子字符串或子字符串中的字符串轮询数据框

从一个系列创建一个Dataframe,特别是如何重命名其中的列(例如:使用NAs/NaN)

如何在Polars中从列表中的所有 struct 中 Select 字段?

cv2.matchTemplate函数匹配失败

Django RawSQL注释字段

用砂箱开发Web统计分析

使用Python查找、替换和调整PDF中的图像'

处理具有多个独立头的CSV文件

如何找出Pandas 图中的连续空值(NaN)?

在Admin中显示从ManyToMany通过模型的筛选结果