qidao123.com技术社区-IT企服评测·应用市场
标题:
leetcode46全分列
[打印本页]
作者:
乌市泽哥
时间:
2025-5-1 18:26
标题:
leetcode46全分列
给定一个不含重复数字的数组 nums ,返回其
所有可能的全分列
。你可以
按恣意次序
返回答案。
示例 1:
<strong>输入:</strong>nums = [1,2,3]
<strong>输出:</strong>[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
复制代码
示例 2:
<strong>输入:</strong>nums = [0,1]
<strong>输出:</strong>[[0,1],[1,0]]
复制代码
示例 3:
<strong>输入:</strong>nums = [1]
<strong>输出:</strong>[[1]]
复制代码
提示:
1 <= nums.length <= 6
-10 <= nums
<= 10
nums 中的所有整数
互不相同
步骤1:题目界说及分析
题目描述
:
给定一个不含重复数字的整数数组 nums,返回其所有可能的全分列。全分列指的是数组中所有元素的不同分列方式。题目要求输出所有分列,可以按照恣意次序返回。
输入输出条件
:
输入:一个不含重复数字的整数数组 nums。
输出:包罗所有可能分列的二维数组。
限制条件
:
1 <= nums.length <= 6
-10 <= nums
<= 10
nums 中的所有整数互不相同。
界限条件
:
数组只有一个元素时,输出应该是该元素的分列,只有一个分列方式。
数组的长度较小(最大为6),因此可以利用递归或回溯算法,性能不会成为瓶颈。
步骤2:题目分解及解题思绪
解题思绪
: 要找出所有分列,我们可以采用
回溯算法
,回溯的焦点头脑是
逐步选择每个位置的元素并进行递归搜索
,当到达终点(即已选择了所有元素)时,就得到了一个分列。
回溯算法计划:
回溯的状态
:每一次递归调用时,选择一个元素加入到当前分列中,剩余元素继续递归生成分列。
剪枝条件
:当某个元素已经被选过时,不再选择该元素。
停止条件
:当分列的长度等于数组长度时,表示已经生成了一个完整的分列,将其加入效果中。
递归步骤:
初始化一个空数组 path 用于存储当前分列。
利用一个布尔数组 used 来标记哪些元素已经被利用过。
通过递归生成分列:
遍历数组中的元素,选择尚未利用的元素加入当前分列。
标记该元素为已利用,递归进入下一层。
当当前分列长度等于 nums 的长度时,表示找到了一个有效的分列,加入效果。
回溯,取消选择,继续尝试其他元素。
时间复杂度与空间复杂度:
时间复杂度
:每个分列的生成时间是 O(n),生成分列的总数是 n!,因此总时间复杂度是 O(n!)。
空间复杂度
:须要存储每次递归状态的栈空间,最大深度为 n,因此空间复杂度是 O(n)。
步骤3:代码实现
以下是基于回溯算法的 C++ 实现:
class Solution {
public:
// 回溯函数
void backtrack(vector<int>& nums, vector<int>& path, vector<bool>& used, vector<vector<int>>& result) {
// 终止条件:当路径长度等于nums长度时,表示找到了一个排列
if (path.size() == nums.size()) {
result.push_back(path);
return;
}
// 遍历nums数组,进行回溯
for (int i = 0; i < nums.size(); i++) {
// 剪枝条件:如果当前元素已经使用过,跳过
if (used[i]) continue;
// 做选择
path.push_back(nums[i]);
used[i] = true;
// 递归生成排列
backtrack(nums, path, used, result);
// 撤销选择
path.pop_back();
used[i] = false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> result;
vector<int> path;
vector<bool> used(nums.size(), false); // 用于标记元素是否被使用
backtrack(nums, path, used, result);
return result;
}
};
复制代码
代码注释:
backtrack 函数负责递归生成分列。它接收参数 nums(输入数组)、path(当前分列路径)、used(元素利用标记)、result(终极效果)。
当 path 的长度等于 nums 的长度时,阐明当前分列已经完成,将其加入到效果 result 中。
通过递归逐步构建分列,每次选一个未被利用的元素加入 path,然后递归。递归完成后,取消选择并继续尝试其他元素。
permute 函数是主函数,负责初始化回溯过程,并返回终极的分列效果。
步骤4:启发与总结
通过这个题目,我们可以获得以下启发:
回溯算法
是处理组合、分列等题目的有力工具,特殊适用于解答具有束缚条件(如每个元素只能出现一次)的分列题目。
回溯算法的焦点头脑在于通过递归逐步构建解空间,利用“选择-递归-取消选择”来枚举所有解。
该算法尤其适用于小规模数据(如 n <= 6 的情况),可以迅速给出精确解。
步骤5:实际应用示例
实际应用场景
:
回溯算法中的分列生成不但适用于底子的算法题,还可以广泛应用于多个实际题目中。比方:
使命调度与资源分配
:在某些使命调度题目中,须要将多个使命安排在多个资源上,包管每个资源的使命次序不重复。回溯算法可以用来生成所有可能的使命安排,并对其进行评估和选择。
旅行商题目(TSP)
:尽管旅行商题目自己是一个NP困难目,但可以通过回溯方法生成所有可能的路径并选择最短路径作为解。
分列组合游戏
:很多游戏和应用中须要生成或评估所有可能的分列。比方,在扑克游戏中,可能须要生成牌的所有组合,进行概率分析或策略优化。
示例
:
假设在某个电子商务平台中,存在多个商品,商家盼望为每个商品选择一个配送方式,并且盼望了解所有可能的配送方案(即分列)。通过回溯算法,我们可以生成所有配送方案,并进行分析,优化物流调度策略。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4