Series01 排列问题 Permutations
一、题型
第 46 题,第 47 题。第 60 题,第 526 题,第 996 题。
46:全排列
47:全排列+去重
60: 输出第k个序列
526:优美的排列
996:正方形数组
二、主要思想
1. 回溯、深度优先遍历
共同点:尽可能尝试所有可能性
回溯:回退
DFS:遍历
2. 与动态规划的区别
动态规划:关心最优解
回溯:关心每一种解的可能性
三、代码
1. 主要代码
(1)记住每一种解的全排列
vector<int> a; //记住序列
vector<int> book;//标记是否被访问:1已经被访问0未被访问--寻求合法状态使用
void Permutations(int k, vector<int> &nums, vector<vector<int>> &all)
{
if(a.size()==k)
{
all.push_back(a);
return;
}
for(int i=0; i<k; i++)
{
//判断状态是否合法
if(book[i]==0)
{
//扩展状态
a.push_back(nums[i]);
book[i] = 1;
DFS(k, nums, all);
//还原状态
book[i] = 0;
a.pop_back();
}
}
}
(2)不记录中间解的全排列--计算多少种
//不用记录中间数组,减轻排列压力
void Permutations(int n, int start, vector<int> nums, vector<bool>& visit, int &total)
{
if(start == n)
{
total++;
return;
}
for(int i=0;i<n;i++)//从1~n选数字,一个一个数字扩张
{
if( (!visit[i])
{
visit[i] = true;
DFS(n, start+1, nums, visit, total);
visit[i] = false;
}
}
}
2. 解题思路
46:全排列
47:全排列+去重
去重:先排序(相同的数字不进行挑选),在确定合法条件时进行剪枝
剪枝一:
if(i>0 && (nums[i]==nums[i-1]) && !book[i-1])//效率更高,重复元素的第一个
{
continue;
}
剪枝二:
if(i>0 && (nums[i]==nums[i-1]) && book[i-1])//重复元素的最后一个
{
continue;
}
60: 输出第k个序列--数学方法
526:优美的排列--类似47-判断合法条件变动
996:正方形数组--类似47-判断合法条件变动
本文来自博客园,作者:circlelll,转载请注明原文链接:https://www.cnblogs.com/circlelll/articles/16614389.html

浙公网安备 33010602011771号