-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
permutations.rs
141 lines (129 loc) · 3.97 KB
/
permutations.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! This module provides a function to generate all possible distinct permutations
//! of a given collection of integers using a backtracking algorithm.
/// Generates all possible distinct permutations of a given vector of integers.
///
/// # Arguments
///
/// * `nums` - A vector of integers. The input vector is sorted before generating
/// permutations to handle duplicates effectively.
///
/// # Returns
///
/// A vector containing all possible distinct permutations of the input vector.
pub fn permute(mut nums: Vec<isize>) -> Vec<Vec<isize>> {
let mut permutations = Vec::new();
let mut current = Vec::new();
let mut used = vec![false; nums.len()];
nums.sort();
generate(&nums, &mut current, &mut used, &mut permutations);
permutations
}
/// Helper function for the `permute` function to generate distinct permutations recursively.
///
/// # Arguments
///
/// * `nums` - A reference to the sorted slice of integers.
/// * `current` - A mutable reference to the vector holding the current permutation.
/// * `used` - A mutable reference to a vector tracking which elements are used.
/// * `permutations` - A mutable reference to the vector holding all generated distinct permutations.
fn generate(
nums: &[isize],
current: &mut Vec<isize>,
used: &mut Vec<bool>,
permutations: &mut Vec<Vec<isize>>,
) {
if current.len() == nums.len() {
permutations.push(current.clone());
return;
}
for idx in 0..nums.len() {
if used[idx] {
continue;
}
if idx > 0 && nums[idx] == nums[idx - 1] && !used[idx - 1] {
continue;
}
current.push(nums[idx]);
used[idx] = true;
generate(nums, current, used, permutations);
current.pop();
used[idx] = false;
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! permute_tests {
($($name:ident: $test_case:expr,)*) => {
$(
#[test]
fn $name() {
let (input, expected) = $test_case;
assert_eq!(permute(input), expected);
}
)*
}
}
permute_tests! {
test_permute_basic: (vec![1, 2, 3], vec![
vec![1, 2, 3],
vec![1, 3, 2],
vec![2, 1, 3],
vec![2, 3, 1],
vec![3, 1, 2],
vec![3, 2, 1],
]),
test_permute_empty: (Vec::<isize>::new(), vec![vec![]]),
test_permute_single: (vec![1], vec![vec![1]]),
test_permute_duplicates: (vec![1, 1, 2], vec![
vec![1, 1, 2],
vec![1, 2, 1],
vec![2, 1, 1],
]),
test_permute_all_duplicates: (vec![1, 1, 1, 1], vec![
vec![1, 1, 1, 1],
]),
test_permute_negative: (vec![-1, -2, -3], vec![
vec![-3, -2, -1],
vec![-3, -1, -2],
vec![-2, -3, -1],
vec![-2, -1, -3],
vec![-1, -3, -2],
vec![-1, -2, -3],
]),
test_permute_mixed: (vec![-1, 0, 1], vec![
vec![-1, 0, 1],
vec![-1, 1, 0],
vec![0, -1, 1],
vec![0, 1, -1],
vec![1, -1, 0],
vec![1, 0, -1],
]),
test_permute_larger: (vec![1, 2, 3, 4], vec![
vec![1, 2, 3, 4],
vec![1, 2, 4, 3],
vec![1, 3, 2, 4],
vec![1, 3, 4, 2],
vec![1, 4, 2, 3],
vec![1, 4, 3, 2],
vec![2, 1, 3, 4],
vec![2, 1, 4, 3],
vec![2, 3, 1, 4],
vec![2, 3, 4, 1],
vec![2, 4, 1, 3],
vec![2, 4, 3, 1],
vec![3, 1, 2, 4],
vec![3, 1, 4, 2],
vec![3, 2, 1, 4],
vec![3, 2, 4, 1],
vec![3, 4, 1, 2],
vec![3, 4, 2, 1],
vec![4, 1, 2, 3],
vec![4, 1, 3, 2],
vec![4, 2, 1, 3],
vec![4, 2, 3, 1],
vec![4, 3, 1, 2],
vec![4, 3, 2, 1],
]),
}
}