字典序实现全排列(字符串的排列c++)

算法学习笔记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);
    }
};

终于通过啦!
在这里插入图片描述



  1. https://www.cnblogs.com/chailinbo/p/9269210.html ↩︎

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值