算法学习笔记5
一、字典序
1.1 字典序的概念
百度百科定义:
给定两个偏序集A和B,(a,b)和(a′,b′)属于笛卡尔积A×B,则字典序定义为
(a,b) ≤ (a′,b′) 当且仅当a<a′ 或 (a=a′ 且b≤b′)。
即给定两个字符串,逐个字符比较,那么先出现较小字符的那个串字典顺序小,如果字符一直相等,较短的串字典顺序小。例如:abc < abcd < abde < afab。1
1.2 字典序的实现原理
图片搬运自互联网,图太经典,引用太多,没有找到原创作者。
总结一下就是:
1、找
2、找
3、交换
4、排序
二、字符串的排列
2.1 题目描述
字符串中有可能有重复的字符。
2.2 思考
上一篇文章图解DFS和回溯(字符串的排列c++)使用DFS和回溯算法实现全排列,并使用c++的set容器去重并按字典序输出,
时间复杂度:O(n!)
空间复杂度:O(1),原地交换
本文使用字典序算法,实现字符串的全排列并按字典序输出:
空间复杂度:O(1),原地交换
因多次使用排序(第一步需要对string整体排序,后续多次需要对字符串局部进行排序),算法时间复杂度相比于DFS回溯算法均有所增加。
2.3 代码实现
sort对string容器排序使用的是迭代器,sort(string.begin(), string.end()),我没有找到string指定位置的迭代器(如有大佬知道,求告知)
所以只能将字符串转换为char*,就可以使用sort(str+s,str+e)的形式进行排序了,其中:
s: string中需要排序的起始位置;
e: string中需要排序的结束位置。
代码如下(参考HankingHu):
class Solution {
public:
vector<string> Permutation(string str) {
int len = str.size();
if(len == 0) return {};
vector<string> ret;
if(len == 1) {
ret.push_back(str);
return ret;
}
else{
sort(str.begin(),str.end());//先对数组的元素进行依次排序
ret.push_back(str);
}
while(true){
int j,index = 0;
for(j=len-2;j>=0;j--){//从右向左找到第一个非递增的元素
if(str[j]<str[j+1]){
index = j;
break;
}
else if (j==0) return ret;//while循环的出口
}
for(j=len-1;j>=0;j--){//从右向左找到第一个比非递增元素大的元素
if(str[j]>str[index]) break;
}
swap(str[index],str[j]);//交换找到的两个元素
resort_str(index+1,len,&str[0]);//对非递增元素位置后面的数组进行逆序排列
ret.push_back(str);
}
}
void resort_str(int s,int e,char* str){//将string转换为char*使用sort算法
sort(str+s,str+e);
}
};
终于通过啦!
https://www.cnblogs.com/chailinbo/p/9269210.html ↩︎