【发布时间】:2019-02-07 02:15:48
【问题描述】:
这是对this thread 的跟进,主要问题是迭代数组的所有排列,即给定["a","b","c"],使用迭代器获得["bca","acb".. etc]。
感谢Martin R 的见解,以及他在另一个thread 中的输入,我想出了使用迭代器的“基于序列的排列枚举”问题的另一种可能的解决方案。问题是我不确定我是否拥有所有排列,尽管有很好的迹象表明它们都在那里。该算法保证提供 n!最多排列,没有重复。
这种方法背后的想法如下,假设有一个数组a=["a","b","c"...],大小为n。列出所有排列可以看作是从包中挑选元素:
■
■
■
■ ■
■ ■ ■
■ ... ■ ■ ■
0 ... n-3 n-2 n-1
所以算法采用初始数组,并删除一行,递归传递它,直到没有剩下的行。此时,如果可以找到迭代器,则可以独立处理所有单独的排列。迭代器隐藏在下面的FactorialSequence 中,其中next() 方法允许从相邻点移动。
public struct FactorialSequence : Sequence, IteratorProtocol {
private var current: [Int]
public init(size:Int) {
self.current = Array(repeating: 0, count: size)
}
public mutating func next() -> [Int]? {
return self.__next();
}
private mutating func __next() -> [Int]? {
var next = current
defer {
current = next;
}
for i in self.current.indices.reversed() {
if next[i] < current.count - i - 1 {
next[i] += 1
return next;
}
next[i] = 0
}
return nil
}
}
func permute(seq:[String],at:[Int]) -> String? {
if seq.count > 0 {
var ss = seq;
let uu = seq[at.first!]
var cc = at;
_ = ss.remove(at: cc.first!)
_ = cc.remove(at: 0);
return uu + (permute(seq:ss,at:cc) ?? "")
}
return nil ;
}
permute() 函数被称为传递从 FactorialSequence 计算的迭代器(一个数组):
var fs = FactorialSequence(size: 3)
print("\(fs.current):\(permute(seq:["a","b","c"], at: fs.current)!)")
while let uu = fs.next() {
print("\(uu):\(permute(seq:["a","b","c"], at: uu)!)")
}
并给出(扁平字符串格式):
[-0.000][-0.000][171] [0, 0, 0]:abc
[0.0009][0.0009][174] [0, 1, 0]:acb
[0.0016][0.0007][174] [1, 0, 0]:bac
[0.0024][0.0008][174] [1, 1, 0]:bca
[0.0032][0.0008][174] [2, 0, 0]:cab
[0.0040][0.0008][174] [2, 1, 0]:cba
关于“无重复”的注意事项:由于使用数组(迭代器)访问排列,如果两个迭代器相差一个元素,则它们指向两个不同的排列。虽然有点薄,但我认为这是没有重复的论据。
剩下的唯一问题是“他们都在那里吗?”。可以说有 n!指向给定排列的不同数组,但我不太确定该论点的有效性,因为它来自“绘图”......欢迎指针。
我没有彻底清理 SO 来检查这是否已经以这种方式或类似方式制定(尽管原始线程中的链接使用其他方法)。抱歉,如果这样做了。
【问题讨论】:
-
那么,您得到的结果数量是否正确,它们是唯一的吗?这应该不难检查。
-
到目前为止,它们已达到我测试的极限,但这几乎不能证明。这篇文章的目的是询问是否有任何通用证明,因为我怀疑上述方法肯定是以前使用过的。我只是找不到在哪里。
标签: arrays swift algorithm permutation