混淆了置换计算中的唯一性
confused on uniqueness in permutation calculation
将以下问题作为一个算法难题进行处理。参考了一些类似的解决方案(并在下面发布了其中一个),尝试了一下,结果奏效了。问题是,对于"swap(num[i],num[k]);"这一行,我们如何确保我们总是可以交换到以前从未尝试过的数字(例如,假设我们在for循环的当前迭代中用2交换1,那么稍后我们可能在递归调用的同一级别/层的相同for循环的下一次迭代中用1交换2)?我有一个困惑,因为我们通过引用传递num,而且以后(较低级别/层)递归调用很可能会修改num的内容,这会导致我们已经评估过的数字交换回来。然而,我尝试过,它适用于我的所有测试用例。想知道下面的解决方案是100%正确的,还是碰巧通过了我的测试用例?:)
以下是我正在调试的详细问题说明和代码,
给定一个可能包含重复的数字集合,返回所有可能的唯一排列。
例如,[1,1,2]具有以下独特的排列:[1,1,2]、[1,2,1]和[2,1,1]
class Solution {
public:
void recursion(vector<int> num, int i, int j, vector<vector<int> > &res) {
if (i == j-1) {
res.push_back(num);
return;
}
for (int k = i; k < j; k++) {
if (i != k && num[i] == num[k]) continue;
swap(num[i], num[k]);
recursion(num, i+1, j, res);
}
}
vector<vector<int> > permuteUnique(vector<int> &num) {
sort(num.begin(), num.end());
vector<vector<int> >res;
recursion(num, 0, num.size(), res);
return res;
}
};
提前感谢,Lin
正如@notmyfriend在评论中所说,num
实际上是在每个函数调用中复制的
所以现在可以归结为:
- 在所有数组值中,选择一个作为第一个值,并将其放置在那里
在循环中为每个值一次,然后递归:- 在第一个值之后的所有值中,选择一个作为第一个值并将其放置在那里
等等,再加上一个检查,过滤掉没有任何变化的交换,即过滤掉重复项。
如果num
是一个真正的参考,它将不再工作(至少没有额外的步骤)
1 12是一个简单的例子,它会给出以下结果:
112, 121, 211, 112, 121
即。尽管进行了检查,但仍存在重复项(可能存在
也是根本不生成某些排列的示例)。
关于评论:
默认情况下,复制C++中的每个正常函数参数
(normal=没有明确的引用符号'&'等)。
也许你想到的是C风格的数组:本质上,传递给那里的是一个指针(指向第一个值)。指针被复制,但原始指针和复制指针都指向相同的内存位置。
虽然std::vector
的目的(也是)包含一个数组,但向量本身是一个单独的类对象(它包含指向某个位置值的指针)。类可以定义自己应该如何复制(使用复制构造函数)
从技术上讲,向量类可以将复制实现为指针复制,那么它将具有与传递整个向量作为引用相同的效果;但是C++创建者希望保留复制语义,即复制容器类应该生成所有值都重复的真实副本
对于非复制,已经有引用。。。
下面可以找到用Java编写的解决方案。很抱歉没有在C++中提供解决方案,我已经很久没有使用它了。但语法会很相似。
解决方案使用回溯(https://en.wikipedia.org/wiki/Backtracking)此外,我使用哈希集来检查唯一性,可能有一种解决方案不使用任何哈希集类型的数据结构,因为我的解决方案使用额外的内存来提供唯一的解决方案。
样本输入和输出;
input : [1, 1, 2]
output : [1, 1, 2]
[1, 2, 1]
[2, 1, 1]
解决方案是;
public class permutation {
public static void main(String[] args) {
permutation p = new permutation();
p.permute(new int[] { 1, 1, 2 });
}
HashSet<String> set = new HashSet<String>();
private void permute(int[] arr) {
set.clear();
this.permute(arr, 0, arr.length - 1);
}
private void permute(int[] arr, int l, int r) {
if (l == r) {
String key = Arrays.toString(arr);
if (set.contains(key))
return;
set.add(key);
System.out.println(key);
} else {
for (int i = l; i <= r; i++) {
swap(arr, l, i);
permute(arr, l + 1, r);
swap(arr, i, l);
}
}
}
private void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
}
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 递归函数计算序列中的平方和(并输出过程)
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的字符计数代码计算错误.为什么
- 在计算中使用二的幂有多有利可图
- 如何计算文件中的"columns"数?
- 计算排序向量的向量中唯一值的计数
- 如何使用 std::累积在 C++ 中计算总和立方体
- 使用Qt C++计算类似Git的SHA1哈希
- OpenCV C++.快速计算混淆矩阵
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- C++如何计算用户输入的数字中的偶数位数
- 如何计算数据类型的范围,例如int
- 类似枚举的计算常量
- 计算每个节点的树高,帮助我解释这个代码解决方案
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 计算缩放多边形的比例,得到给定的多边形面积
- 在C++中如何在没有pow的情况下进行基础计算
- 计算平均值,不包括上次得分
- 混淆了置换计算中的唯一性