|
1 |
| -/* |
2 |
| -The permutations problem involves finding all possible permutations |
3 |
| -of a given collection of distinct integers. For instance, given [1, 2, 3], |
4 |
| -the goal is to generate permutations like |
5 |
| - [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], and [3, 2, 1]. |
6 |
| - This implementation uses a backtracking algorithm to generate all possible permutations. |
7 |
| -*/ |
8 |
| - |
9 |
| -pub fn permute(nums: Vec<i32>) -> Vec<Vec<i32>> { |
10 |
| - let mut result = Vec::new(); // Vector to store the resulting permutations |
11 |
| - let mut current_permutation = Vec::new(); // Vector to store the current permutation being constructed |
12 |
| - let mut used = vec![false; nums.len()]; // A boolean array to keep track of used elements |
13 |
| - |
14 |
| - backtrack(&nums, &mut current_permutation, &mut used, &mut result); // Call the backtracking function |
15 |
| - |
16 |
| - result // Return the list of permutations |
| 1 | +//! This module provides a function to generate all possible distinct permutations |
| 2 | +//! of a given collection of integers using a backtracking algorithm. |
| 3 | +
|
| 4 | +/// Generates all possible distinct permutations of a given vector of integers. |
| 5 | +/// |
| 6 | +/// # Arguments |
| 7 | +/// |
| 8 | +/// * `nums` - A vector of integers. The input vector is sorted before generating |
| 9 | +/// permutations to handle duplicates effectively. |
| 10 | +/// |
| 11 | +/// # Returns |
| 12 | +/// |
| 13 | +/// A vector containing all possible distinct permutations of the input vector. |
| 14 | +pub fn permute(mut nums: Vec<isize>) -> Vec<Vec<isize>> { |
| 15 | + let mut permutations = Vec::new(); |
| 16 | + let mut current = Vec::new(); |
| 17 | + let mut used = vec![false; nums.len()]; |
| 18 | + |
| 19 | + nums.sort(); |
| 20 | + generate(&nums, &mut current, &mut used, &mut permutations); |
| 21 | + |
| 22 | + permutations |
17 | 23 | }
|
18 | 24 |
|
19 |
| -fn backtrack( |
20 |
| - nums: &Vec<i32>, |
21 |
| - current_permutation: &mut Vec<i32>, |
| 25 | +/// Helper function for the `permute` function to generate distinct permutations recursively. |
| 26 | +/// |
| 27 | +/// # Arguments |
| 28 | +/// |
| 29 | +/// * `nums` - A reference to the sorted slice of integers. |
| 30 | +/// * `current` - A mutable reference to the vector holding the current permutation. |
| 31 | +/// * `used` - A mutable reference to a vector tracking which elements are used. |
| 32 | +/// * `permutations` - A mutable reference to the vector holding all generated distinct permutations. |
| 33 | +fn generate( |
| 34 | + nums: &[isize], |
| 35 | + current: &mut Vec<isize>, |
22 | 36 | used: &mut Vec<bool>,
|
23 |
| - result: &mut Vec<Vec<i32>>, |
| 37 | + permutations: &mut Vec<Vec<isize>>, |
24 | 38 | ) {
|
25 |
| - if current_permutation.len() == nums.len() { |
26 |
| - // If the current permutation is of the same length as the input, |
27 |
| - // it is a complete permutation, so add it to the result. |
28 |
| - result.push(current_permutation.clone()); |
| 39 | + if current.len() == nums.len() { |
| 40 | + permutations.push(current.clone()); |
29 | 41 | return;
|
30 | 42 | }
|
31 | 43 |
|
32 |
| - for i in 0..nums.len() { |
33 |
| - if used[i] { |
34 |
| - continue; // Skip used elements |
| 44 | + for idx in 0..nums.len() { |
| 45 | + if used[idx] { |
| 46 | + continue; |
| 47 | + } |
| 48 | + |
| 49 | + if idx > 0 && nums[idx] == nums[idx - 1] && !used[idx - 1] { |
| 50 | + continue; |
35 | 51 | }
|
36 | 52 |
|
37 |
| - current_permutation.push(nums[i]); // Add the current element to the permutation |
38 |
| - used[i] = true; // Mark the element as used |
| 53 | + current.push(nums[idx]); |
| 54 | + used[idx] = true; |
39 | 55 |
|
40 |
| - backtrack(nums, current_permutation, used, result); // Recursively generate the next permutation |
| 56 | + generate(nums, current, used, permutations); |
41 | 57 |
|
42 |
| - current_permutation.pop(); // Backtrack by removing the last element |
43 |
| - used[i] = false; // Mark the element as unused for the next iteration |
| 58 | + current.pop(); |
| 59 | + used[idx] = false; |
44 | 60 | }
|
45 | 61 | }
|
46 | 62 |
|
47 | 63 | #[cfg(test)]
|
48 | 64 | mod tests {
|
49 | 65 | use super::*;
|
50 | 66 |
|
51 |
| - #[test] |
52 |
| - fn test_permute() { |
53 |
| - // Test case: Generate permutations for [1, 2, 3] |
54 |
| - let permutations = permute(vec![1, 2, 3]); |
55 |
| - |
56 |
| - assert_eq!(permutations.len(), 6); // There should be 6 permutations |
| 67 | + macro_rules! permute_tests { |
| 68 | + ($($name:ident: $test_case:expr,)*) => { |
| 69 | + $( |
| 70 | + #[test] |
| 71 | + fn $name() { |
| 72 | + let (input, expected) = $test_case; |
| 73 | + assert_eq!(permute(input), expected); |
| 74 | + } |
| 75 | + )* |
| 76 | + } |
| 77 | + } |
57 | 78 |
|
58 |
| - // Verification for some of the permutations |
59 |
| - assert!(permutations.contains(&vec![1, 2, 3])); |
60 |
| - assert!(permutations.contains(&vec![1, 3, 2])); |
61 |
| - assert!(permutations.contains(&vec![2, 1, 3])); |
| 79 | + permute_tests! { |
| 80 | + test_permute_basic: (vec![1, 2, 3], vec![ |
| 81 | + vec![1, 2, 3], |
| 82 | + vec![1, 3, 2], |
| 83 | + vec![2, 1, 3], |
| 84 | + vec![2, 3, 1], |
| 85 | + vec![3, 1, 2], |
| 86 | + vec![3, 2, 1], |
| 87 | + ]), |
| 88 | + test_permute_empty: (Vec::<isize>::new(), vec![vec![]]), |
| 89 | + test_permute_single: (vec![1], vec![vec![1]]), |
| 90 | + test_permute_duplicates: (vec![1, 1, 2], vec![ |
| 91 | + vec![1, 1, 2], |
| 92 | + vec![1, 2, 1], |
| 93 | + vec![2, 1, 1], |
| 94 | + ]), |
| 95 | + test_permute_all_duplicates: (vec![1, 1, 1, 1], vec![ |
| 96 | + vec![1, 1, 1, 1], |
| 97 | + ]), |
| 98 | + test_permute_negative: (vec![-1, -2, -3], vec![ |
| 99 | + vec![-3, -2, -1], |
| 100 | + vec![-3, -1, -2], |
| 101 | + vec![-2, -3, -1], |
| 102 | + vec![-2, -1, -3], |
| 103 | + vec![-1, -3, -2], |
| 104 | + vec![-1, -2, -3], |
| 105 | + ]), |
| 106 | + test_permute_mixed: (vec![-1, 0, 1], vec![ |
| 107 | + vec![-1, 0, 1], |
| 108 | + vec![-1, 1, 0], |
| 109 | + vec![0, -1, 1], |
| 110 | + vec![0, 1, -1], |
| 111 | + vec![1, -1, 0], |
| 112 | + vec![1, 0, -1], |
| 113 | + ]), |
| 114 | + test_permute_larger: (vec![1, 2, 3, 4], vec![ |
| 115 | + vec![1, 2, 3, 4], |
| 116 | + vec![1, 2, 4, 3], |
| 117 | + vec![1, 3, 2, 4], |
| 118 | + vec![1, 3, 4, 2], |
| 119 | + vec![1, 4, 2, 3], |
| 120 | + vec![1, 4, 3, 2], |
| 121 | + vec![2, 1, 3, 4], |
| 122 | + vec![2, 1, 4, 3], |
| 123 | + vec![2, 3, 1, 4], |
| 124 | + vec![2, 3, 4, 1], |
| 125 | + vec![2, 4, 1, 3], |
| 126 | + vec![2, 4, 3, 1], |
| 127 | + vec![3, 1, 2, 4], |
| 128 | + vec![3, 1, 4, 2], |
| 129 | + vec![3, 2, 1, 4], |
| 130 | + vec![3, 2, 4, 1], |
| 131 | + vec![3, 4, 1, 2], |
| 132 | + vec![3, 4, 2, 1], |
| 133 | + vec![4, 1, 2, 3], |
| 134 | + vec![4, 1, 3, 2], |
| 135 | + vec![4, 2, 1, 3], |
| 136 | + vec![4, 2, 3, 1], |
| 137 | + vec![4, 3, 1, 2], |
| 138 | + vec![4, 3, 2, 1], |
| 139 | + ]), |
62 | 140 | }
|
63 | 141 | }
|
0 commit comments