Permutations II - Go Solution
Solving the LeetCode "Permutations II" Problem in Go
Introduction
The "Permutations II" problem requires generating all unique permutations of an array that may contain duplicate elements. Unlike the standard permutations problem, handling duplicates efficiently is crucial to avoid redundant results.
Problem Analysis
Given an array of integers with possible duplicates, the task is to return all unique permutations. For example, for the input [1,1,2], the output should include [1,1,2], [1,2,1], and [2,1,1], but no duplicates of these permutations.
Solution Approach
To solve this problem, we use a backtracking approach combined with sorting to skip duplicate elements. The steps are as follows:
- Sort the input array to group duplicates together.
- Use a backtracking function to generate permutations while skipping duplicates.
- Track used elements to avoid reusing the same element in the same permutation.
Go Implementation
package main
import (
"fmt"
"sort"
)
func permuteUnique(nums []int) [][]int {
var result [][]int
sort.Ints(nums)
backtrack(&result, nums, []int{}, make([]bool, len(nums)))
return result
}
func backtrack(result *[][]int, nums, current []int, used []bool) {
if len(current) == len(nums) {
temp := make([]int, len(current))
copy(temp, current)
*result = append(*result, temp)
return
}
for i := 0; i < len(nums); i++ {
if used[i] || (i > 0 && nums[i] == nums[i-1] && !used[i-1]) {
continue
}
used[i] = true
current = append(current, nums[i])
backtrack(result, nums, current, used)
used[i] = false
current = current[:len(current)-1]
}
}
func main() {
fmt.Println(permuteUnique([]int{1, 1, 2}))
fmt.Println(permuteUnique([]int{1, 2, 3}))
}
Complexity Analysis
Time Complexity: O(N * N!), where N is the number of elements in the input array. The sorting step takes O(N log N), but the dominant factor is the backtracking step, which generates N! permutations.
Space Complexity: O(N), due to the recursion stack and the auxiliary array used to track visited elements.
Testing and Examples
Test cases include:
- Input: [1,1,2] → Output: [[1,1,2], [1,2,1], [2,1,1]]
- Input: [1,2,3] → Output: [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
- Edge Case: [1] → Output: [[1]]
Best Practices and Tips
Key takeaways:
- Always sort the input array to handle duplicates efficiently.
- Use a boolean array to track used elements and avoid reusing them in the same permutation.
- Skip duplicates by checking if the current element is the same as the previous and the previous is unused.