去年写不出全排列,今天终于完成,前来还愿
新增组合代码
非重复排列
使用分治递归,按位逐层交换,记录底层交换结果,恢复交换并返回
def swap(s, i1, i2):
if i1 < len(s) and i2 < len(s):
s[i1], s[i2] = s[i2], s[i1]
def arrange(s, begin, end):
if begin == end:
print(s)
return
for i in range(begin, end):
swap(s, begin, i)
arrange(s, begin + 1, end)
swap(s, begin, i)
s = [x for x in 'abcd']
arrange(s, 0, len(s))
非重复组合
类似排列代码,添加交换约束,在最后已取元素原位置后开始取下一元素
ps:可以使用itertools.combination(s,n)
,但其无法处理集合中有重复元素时的情况
def swap(s, i1, i2):
if i1 < len(s) and i2 < len(s):
s[i1], s[i2] = s[i2], s[i1]
def combination(s, begin, mid, end, last, n):
if end - begin < last:
return
if last == 0:
print(s[:n])
return
for i in range(mid, end):
swap(s, begin, i)
combination(s, begin + 1, i + 1, end, last - 1, n)
swap(s, begin, i)
s = [3, 7, 12, 19]
combination(s, 0, 0, len(s), n, n)
重复排列
使用进制原理,迭代取余映射,记录映射结果
import numpy as np
def cumdivision(i, base, n):
arr = []
while i > 0:
arr.append(i % base)
i = i // base
arr.extend([0] * (n - len(arr)))
return arr[::-1]
def arrange(s, n):
base = len(s)
for i in range(pow(base, n)):
arr = cumdivision(i, base, n)
print(np.array(s)[arr])
s = [x for x in 'abcd']
arrange(s, 4)