Python 解决方案可以转换为迭代器:
use std::collections::btree_set::{BTreeSet, IntoIter};
enum UniquePermutations {
Leaf {
elements: Option<Vec<i32>>,
},
Stem {
elements: Vec<i32>,
unique_elements: IntoIter<i32>,
first_element: i32,
inner: Box<Self>,
},
}
impl UniquePermutations {
fn new(elements: Vec<i32>) -> Self {
if elements.len() == 1 {
let elements = Some(elements);
Self::Leaf { elements }
} else {
let mut unique_elements = elements
.clone()
.into_iter()
.collect::<BTreeSet<_>>()
.into_iter();
let (first_element, inner) = Self::next_level(&mut unique_elements, elements.clone())
.expect("Must have at least one item");
Self::Stem {
elements,
unique_elements,
first_element,
inner,
}
}
}
fn next_level(
mut unique_elements: impl Iterator<Item = i32>,
elements: Vec<i32>,
) -> Option<(i32, Box<Self>)> {
let first_element = unique_elements.next()?;
let mut remaining_elements = elements;
if let Some(idx) = remaining_elements.iter().position(|&i| i == first_element) {
remaining_elements.remove(idx);
}
let inner = Box::new(Self::new(remaining_elements));
Some((first_element, inner))
}
}
impl Iterator for UniquePermutations {
type Item = Vec<i32>;
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::Leaf { elements } => elements.take(),
Self::Stem {
elements,
unique_elements,
first_element,
inner,
} => loop {
match inner.next() {
Some(mut v) => {
v.insert(0, *first_element);
return Some(v);
}
None => {
let (next_fe, next_i) =
Self::next_level(&mut *unique_elements, elements.clone())?;
*first_element = next_fe;
*inner = next_i;
}
}
},
}
}
}
fn main() {
let items = vec![0, 0, 1, 2];
for perm in UniquePermutations::new(items) {
println!("{:?}", perm);
}
}
生成器解决方案隐藏了很多分配和复杂性,这在此处被带到了最前沿。调用堆栈变成了字段的链表inner
,我们必须进行大量的克隆。
我没有执行任何微优化,例如使用 aVecDeque
插入列表的头部,或者添加一个包装迭代器适配器,Vec
在最终将其返回给调用者之前将其反转。我还用 aBTreeSet
来专注于确保集合是独一无二的;随意将其更改为基于纯Vec
的解决方案。
我也没有进行任何分析或基准测试。这可能会也可能不会更快。
crates.io 上有许多排列板条箱可用。我鼓励您查看是否可以将这段代码添加到其中的一个或多个中,以防止人们将来不得不解决这个问题。