有多种方法可以找到具有重复项的整数数组的所有排列。在这里,我只讨论递归方法而不使用额外的" visited []"阵列。
正确的方法是:
void helper(vector<vector<int>>& ans, vector<int> nums, int pos) {
if(pos == nums.size()-1) {
ans.push_back(nums);
return;
}
for(int i = pos; i < nums.size(); i++) {
if(i == pos || nums[i] != nums[pos]) {
swap(nums[i], nums[pos]);
helper(ans, nums, pos+1);
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> ans;
sort(nums.begin(), nums.end());
helper(ans, nums, 0);
return ans;
}
我不太清楚为什么它将nums []作为副本传递给递归函数。所以我环顾四周geeks for geeks,它说&#34;想法是在第一个索引处修复第一个字符并递归调用其他后续索引&#34;。我以为我可以修复第一个字符,然后通过传递nums []作为参考来递归调用其他后续索引,并且&#34;交换回&#34;当递归完成时(如下所示)。但遗憾的是它没有用。
void helper(vector<vector<int>>& ans, vector<int>& nums, int pos) {
if(pos == nums.size()-1) {
ans.push_back(nums);
return;
}
for(int i = pos; i < nums.size(); i++) {
if(i == pos || nums[i] != nums[i-1]) {
swap(nums[i], nums[pos]);
helper(ans, nums, pos+1);
swap(nums[i], nums[pos]);
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> ans;
sort(nums.begin(), nums.end());
helper(ans, nums, 0);
return ans;
}
我想知道将nums []作为参考传递给递归时出了什么问题?为什么将nums []副本传递给递归是正确的?
答案 0 :(得分:0)
我想我找到了原因。通过值传递并通过引用传递给出两个完全不同的算法。要明白这一点。让我们首先注意两个重要的观察结果:
我们做的第一件事是对数组进行排序,为什么?因为我们希望以“下一个排列”顺序访问所有排列,即123,132,213,231,312,321。这样就不会有重复。
下一次递归中的子问题也维护了sorted属性。让我们用一个例子来说明这一点。 输入nums = [1,2,2,3]将值传递给递归,其中pos = 0,
i = 0:子问题是[2,2,3],
i = 1:子问题是[1,2,3],
i = 2:跳过,
i = 3子问题是[1,2,2]。
此递归级别中的所有子问题都是SORTED。 但是如果[1,2,2,3]通过引用传递,则子问题不会被排序,因此您无法回复“下一个排列”方法来为您提供非重复的排列。
如果您仍感到困惑,请花点时间阅读以下讨论: https://discuss.leetcode.com/topic/8831/a-simple-c-solution-in-only-20-lines/28?page=2