46.全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
方法一:不用swap回溯状态
第二个swap函数的作用是保证在整个for循环中,每一次循环开始时,序列都保持和刚进入本次递归时一致,事实上并没有这个必要。
如果用swap恢复状态会出现什么问题呢?假设序列为nums[t],nums[t+1],...,nums[k],nums[k+1],...,到了要交换nums[t]和nums[k]位置的时候,序列变为nums[k],nums[t+1],...,nums[t],nums[k+1],... 。那么进入下一次递归要处理的序列就是nums[t+1],...,nums[t],nums[k+1],... ,但是这个序列并不是有序的,因此也就不能保证最后的结果保持字典序。
而如果不恢复状态,到了要交换nums[t]和nums[k]位置的时候,序列则是变成nums[k],nums[t],...,nums[k-1],nums[k+1],...,也就相当于nums[k]放在了t位置,而原序列t到k-1位置的元素全都右移了一位,nums[t],...,nums[k-1],nums[k+1],...依然有序,因此进入下一次递归时要处理的序列仍旧有序。
vector<vector<int>> res;
//这里的nums不用引用,它是各个节点当前状态对应的序列,这些序列互不相同。
void backtrack(int t,vector<int> nums){
if(t==nums.size()) {
res.push_back(nums);
return;
}
for(int i=t;i<nums.size();++i){
swap(nums[i],nums[t]);
backtrack(t+1,nums);
//swap(nums[i],nums[t]);
}
}
vector<vector<int>> permute(vector<int>& nums) {
backtrack(0,nums);
return res;
}
方法二:for循环之前对待选部分排序
vector<vector<int>> res;
//这里的nums不用引用,它是各个节点当前状态对应的序列,这些序列互不相同。
void backtrack(int t,vector<int> nums){
if(t==nums.size()) {
res.push_back(nums);
return;
}
sort(nums.begin()+t,nums.end());
for(int i=t;i<nums.size();++i){
swap(nums[i],nums[t]);
backtrack(t+1,nums);
swap(nums[i],nums[t]);
}
}
vector<vector<int>> permute(vector<int>& nums) {
backtrack(0,nums);
return res;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 2025成都.NET开发者Connect圆满结束