全排列
全排列属于组合数学的知识,有序数法,字典序法,临位互换法,本文着重从字典序法(stl中的Next_permutation也是使用此法)对字符串s进行全排列。具体算法如下:
I)从后往前找到第一个j,使得s[j]<s[j+1],若未找到,即j=-1时结束
II)从后往前找到第一个k,使得s[k] > s[j],然后交换s[k],s[j]
III)将s[j+1:n]倒置
对于这种算法是如何得到全排列的证明如下:
1.子串s[j+1:n]是单调递减的,即对于前半部分为s[0:j]的当前字符串而言,后半部分是全排列的最大值
2.s[k]是从后往前找到的第一个大于s[j]的字符,所以交换后,得到的字符串是下一轮排列的最大值
故只要将s[j+1:n](交换后)倒置即得到next_permutation
#include <stdio.h> #include <string.h> #define swap(a,b){char tmp=a;a=b;b=tmp;} //a=a+b;b=a-b;a=a-b; #define N 50 void Permutation(char *s){ int i,j,k; while(1){ puts(s); for(j = strlen(s) - 2 ; j >= 0 ; j --) if(s[j] < s[j+1]){ //第一个比右边小 break; } if(j == -1) break; //已得到最大全排列 for(i = strlen(s) - 1 ; i >= 0 ; i -- ) if(s[i] > s[j]){ swap(s[i],s[j]); break; //need break } for(i = j + 1 ; i <= (strlen(s)-1+j)/2 ; i ++ ) //从j开始的子串倒置,need"=" swap(s[i],s[strlen(s)+j-i]); } } int main(){ char s[N] = "1234"; Permutation(s); return 0; }
显然,我们注意到字典序法适用于:无重复但需要初始状态按ascii码升序字符串全排列
对于存在重复的字符串以及有序数法和临位互换法的实现将在以后的文章中讲解。。。
参考资料:
http://blog.csdn.net/cpfeed/article/details/7376132
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 别做抢活的导演:代码中的抽象层次原则
· 从 Redis 客户端超时到 .NET 线程池挑战
· C23和C++26的#embed嵌入资源指南
· 「EF Core」框架是如何识别实体类的属性和主键的
· 独立开发,这条路可行吗?
· 他没买 iPad,而是花了半年时间,为所有“穷学生”写了个笔记神器
· Visual Studio 现已支持新的、更简洁的解决方案文件(slnx)格式
· 从 Redis 客户端超时到 .NET 线程池挑战:饥饿、窃取与阻塞的全景解析
· 2025年中总结:我想我克服公众演讲的恐惧了,一个社恐分子突破自我的故事
· 3.1k star!推荐一款开源基于AI实现的浏览器自动化插件工具 !