字符串全排列算法_C#版_剑指OFFER
题目描述
题目描述
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
数据范围: n < 10n<10
要求: 空间复杂度 O(n!)O(n!),时间复杂度 O(n!)O(n!)
输入描述: 输入一个字符串,长度不超过10,字符只包括大小写字母。
思路
显然此题为递归思维。固定一个字符,依次与剩下的字符进行交换,然后固定下一个,思想类似于排列…
首先,将字符串分为两个部分,一部分为用于交换的固定串,一部分为等待交换的交换串。为方便讲解,将固定串中字符称为固定字符,交换串中的字符称为交换字符。
那么其递归顺序是这样的:
- 固定第一个字符,与剩下交换串substr依次交换
- 将substr视做第一个字符串,固定substr的第一个字符,进行操作1,直到substr长度为0,结束递归
- 第一个固定字符使用完毕,开始固定第二个字符,与剩下的字符串substr依次交换字符值
- 重复上述步骤,直至所有字符都固定过
此时,会有重复字符串的问题。固定字符与交换字符相同,那就白交换了。这时可以设置不相同时才交换。
但还是会有重复问题:
比如a b1 b2,
按照思路,
第一轮
固定a
交换一次后,得到b1 a b2,substr (a,b2 ) 交换后得到b1 b2 a,(第二步)
a b1 b2交换第二次,得到b2 b1 a,此时就重复了
此时发生重复问题是因为进入递归后,substr可当做一个独立字符串,前面的固定字符串无法影响substr产生的交换字符串,显而易见地,substr字符串拥有的字母与数量相同,则会产生重复的排列。
为了解决这个问题,就提前掐断字母全都相同的substr。
判断当前交换字符,与固定字符之间的串(称为中间串)是否有与其重复的字符,如果有,就取消交换。
比如a b1 c b2 d,
按照思路,
第一轮固定a,
交换第一次得到,b1 a c b2 ,
substr (a,c,b2 ) 总会得到交换串 b2,c,a
而a与b2交换后得b2 b1 c a ,此字符串进入递归后substr(b1,c,a) 肯定会产生重复排列
using System.Collections.Generic;
using System;
class Solution
{
public List<string> Permutation(string str)
{
// write code here
List<string> res = new List<string>();
if(str.Length==0)return res;
recursion(0,str,ref res);
return res;
}
public void recursion(int fixedIdx,string str,ref List<string> res)
{
// write code here
//注意 string是不可修改的,故要转换为字符串数组
char [] newstr = str.ToCharArray();
res.Add(str); //添加初始串
int curIdx;
while(fixedIdx<str.Length)
{ //固定字符依次向前推进
for(curIdx=fixedIdx+1;curIdx<str.Length;curIdx++)
{
if(is_swap(fixedIdx,curIdx,newstr)){
swap(fixedIdx,curIdx,ref newstr); //交换
recursion(fixedIdx+1,new string(newstr),ref res); //从此串确定的位置后一位开始递归
newstr=str.ToCharArray(); //复原
}
}
fixedIdx++;
}
}
//防止与前面会产生的交换串重复, 递归字符串拥有的字母与数量相同,则会输出重复的排列
//保证相似的字符串只会输出一次
public bool is_swap(int fixedIdx,int curIdx,char[] newstr)
{
int idx=curIdx-1; //依次比较中间串是否有相等字符,若有返回false,跳过这轮交换
while(idx>=fixedIdx)
{
if(newstr[idx]==newstr[curIdx])
return false;
idx--;
}
return true;
}
//交换
public void swap(int fixedIdx,int idx,ref char[] substr)
{
char tmp=substr[fixedIdx];
substr[fixedIdx]=substr[idx];
substr[idx]=tmp;
}
}