剑指 Offer 38. 字符串的排列
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 38. 字符串的排列相关的知识,希望对你有一定的参考价值。
题目链接: 剑指 Offer 38. 字符串的排列
有关题目
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]
限制:
1 <= s 的长度 <= 8
题解
法一:回溯
思路:
将这个问题看作有 n 个排列成一行的空位,我们需要从左往右
依次填入题目给定的 n 个字符,每个字符只能使用一次。
使用穷举法从左往右,依次填入字符
class Solution {
public:
//创建全局变量数组,减少回溯函数传参
vector<string> rec;
vector<int> vis;
void backtrack(const string& s,int i,int n,string& perm)
//s 获得全排列的源字符串 i 下一个待填入的空位是第 i 个空位
//n = s.length() perm 当前排序
{
if (i == n)//递归终止条件
{
rec.push_back(perm);
return;
}
else
{
for (int j = 0; j < n; j++)
{
//在递归函数中,我们限制每次填入的字符一定是这个字符所在重复字符集合中「从左往右第一个未被填入的字符」保证生成不重复序列的必要条件
if ((vis[j] || (j > 0 && !vis[j - 1] && s[j - 1] == s[j])))
continue;
vis[j] = true;//标记
perm.push_back(s[j]);
backtrack(s,i + 1,n,perm);
perm.pop_back();//拿掉上一个函数,防止数据污染
vis[j] = false;//使用完,拿掉标记
}
}
}
vector<string> permutation(string s) {
int n = s.length();
vis.resize(n);
sort(s.begin(),s.end());//给字符串排序,保证生成不重复序列的必要条件
string perm;//定义backtrack函数中的当前 排序
backtrack(s,0,n,perm);//调用回溯函数
return rec;
}
};
法二:下一个排列
思路:
结合next_permutation()函数思想,避免分类讨论,找出的一定是避免重复的字符串,下图附next_permutation函数的排列顺序
class Solution {
public:
bool nextPermutation(string& s)
{
int i = s.length() - 2;
while(i >= 0 && s[i] >= s[i + 1])
--i;
if (i < 0)
return false;
int j = s.length() - 1;
while(j >= 0 && s[i] >= s[j])
--j;
swap(s[i],s[j]);
reverse(s.begin() + i + 1,s.end());
return true;
}
vector<string> permutation(string s) {
vector<string> ret;
sort(s.begin(),s.end());
do
{
ret.push_back(s);
}while(nextPermutation(s));
return ret;
}
};
以上是关于剑指 Offer 38. 字符串的排列的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode(剑指 Offer)- 38. 字符串的排列