问题描述

打印给定字符串的所有排列情况。
例如 输入字符串‘abc’,则打印出它的全排列形式:
abc acb bac bca cab cba
【注意】写算法时要考虑到有相同元素的情况:
输入字符串‘aab’,它的全排列打印应该为 aab aba baa
所以,设计的算法应该对没有重复元素有重复元素这两种情况有区分

方法一:递归实现—通俗易懂

1)把字符串分成两部分:一部分是字符串第一个字符,另一部分是第一个字符以后的所有字符,接下来求第一个字符以后的所有字符的排列
2)拿第一个字符和它后面的字符逐个交换

递归代码—-推荐此法

/***************************************
Author:tmw
date:2018-7-2
***************************************/
#include <stdio.h>
#include <stdlib.h>void char_all_permutate( char* str )
{/**入参检查**/if( str == NULL )return;permutate( str,str );
}/**
* 递归全排列
* @param *str
* @param *begin_p  -- 记录排列挪动的位置
*/
#define swap( a,b,t ) (t=a,a=b,b=t)
void permutate( char* str, char* begin_p )
{if( *begin_p == '\0' ) /**begin_p是指针**/printf("%s\n",str);else{char* p;for( p=begin_p; p != '\0'; p++ ){char temp;swap( *begin_p,*p,temp );permutate(str,begin_p+1);swap( *begin_p,*p,temp );//还原之前的状态}}
}

方法二:递归实现

先确定一个数作为排列的第一个字符,然后对剩余的字符进行全排列,经过层层递归,从右到左慢慢覆盖所有的全排列情况。

递归代码

/************************
Author:tmw
date:2017-11-9
************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
/**递归算法实现**/
//#define swap(x,y,t) (t=x,x=y,y=t)---宏定义方法
void swap( char* array , int i , int j ) //---函数实参传递方法
{char temp;temp = array[i];array[i] = array[j];array[j] = temp;
}
bool can_swap( char *array , int i , int left );
void char_all_permutate(char array[] , int left , int right )
{int i;if( left == right )printf("\t %s\n",array);for( i = left ; i <= right ; i++ ){if(can_swap(array,left,i)){swap(array,i,left);//对i位置以后的元素进行全排序,如此递归char_all_permutate(array,left+1,right);//返回上一层的同时恢复上一层序列排序,以防i叠加后,进入第一个swap时,又和之前相同的元素调换了,打印相同交换结果//---真正实现与i位置元素轮流调换的功能swap(array,i,left);}}
}
//以上子函数虽能实现对字符数组的全排列,但是如果排列元素中有重复的元素,此全排列算法会失效
//因为此算法没有对元素判重区分后再交换,因此,优化此算法的点在于,优化swap,对swap增加一个元素判重的判定//元素非重复,返回true,可交换
bool can_swap( char *array , int left , int i )
{//由于i起始位置是left,因此在判断待交换的两个元素是否需要交换时应避免i=left的情况int kk = left;for( kk = left ; kk < i ; kk++)if( array[kk] == array[i] && i != kk )return false;return true;
}

方法二:字典序全排列

字典序排列算法

给定两个偏序集A和B,(a,b)和(a′,b′)属于笛卡尔积A×B,则字典序定义为(a,b) ≤ (a′,b′) 当且仅当 a小于a′ 或 (a=a′ 且b≤b′).
1)如果给定的两个等长字符串,从起点开始将它们对应的字符逐个比较,则先出现较小字符的字符串字典序小
2)如果给定的是两个非等长字符串,如果字符一直相等,则较短那个字符串的字典序小

例如:“abc”、“abcd”、“acde”、“adbc”
字典序从小到大排列为:”abc”、“abcd”、“acde”、“adbc”

所以,要求出给定任意字符串的全排列,则采用字典序排序算法如下:

算法起点:找到字典序最小的排列1~n,如“12345”
step1:从右至左找寻字符串中第一次出现递减序列的首位字符a[i];
step2:寻找i位置往右的字符中,比a[i]大的所有字符里面最小的字符,记为b[j];
step3:交换a[i]与b[j];
step4:把第i+1位到最后部分的字符翻转,执行此步骤后,i+1到n的字符变成升序排列
算法终点:找到字典序最大的排列n~1,如“54321”,算法结束

字典序排列代码实现

/**字典序排列算法实现**/
/************************
Author:tmw
date:2017-11-12
************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>#define swap(x,y,t) (t=x,x=y,y=t)
//算法起点:普通快排找出已给字符串的字典序最小排列
int first_ele_fast_sort( char* array , int low , int high )//注意是针对字符串的快排  char
{int target = 0;target = array[low];//偷个懒,直接用数组中的第一个元素作为中轴元素while( low < high ){while( low < high && array[high] >= target  )high--;array[low] = array[high];//此时high位置上的元素为待处理元素while( low < high && array[low] <= target   )low++;array[high] = array[low];//将大于target值的元素放到待处理的high位置上,那么此时,low位置变为待处理}array[low] = target; //以上,省去交换,变为“挖坑赋值”,降低时间复杂度return low;
}
char* fast_sort( char* array , int low , int high )
{if( low < high ){int index;index = first_ele_fast_sort(array,low,high);fast_sort(array,low,index-1);fast_sort(array,index+1,high);}return array;
}void reverse( char* array , int start , int end )
{while( start < end ){char temp;swap(array[start],array[end],temp);start++;end--;}
}//字典序排列算法----找到比当前排列字典序大1的新排列
bool dictionary_sort( char* array , int array_len )
{//step1:从右至左找寻字符串中第一次出现递减序列的首位字符a[i]int i = 0;int j = 0;for( i = array_len - 2 ; (i >= 0) && array[i] >= array[i+1] ; i-- );//此时i位置上的元素array[i]即为目标元素aif( i < 0 )//说明此时已经是最大字典序列return false;//step2:寻找i位置往右的字符中,比a[i]大的所有字符里面最小的字符,记为b[j];for( j = array_len-1 ; ( j > i ) && array[j] <= array[i] ; j-- );//for循环后,就找到了第二个目标元素b---array[j]//step3:交换a[i]与b[j]char temp;swap(array[j],array[i],temp);//step4:把第i+1位到最后部分的字符翻转reverse(array,i+1,array_len-1);return true;
}/**字典序全排列--找出给定字符串按字典序从小到大找出全排列**/
void dictionary_full_sort(char* array , int array_len )
{int i = 1;array = fast_sort(array,0,array_len-1);//先快排,找出最小字典序列printf("\tcase #%d \t%s\n",i,array);while(dictionary_sort(array,array_len))printf("\tcase #%d \t%s\n",++i,array);
}

28-字符串全排列问题相关推荐

  1. 面试题28:字符串全排列

    字符串全排列是面试中常考的问题,一定要掌握 这题没写出来,思路就是把第一个字符和后面所有字符交换,然后递处理后面n-1个,最后需要在调用交换函数换回原始字符串 1 #include<iostre ...

  2. 求字符串全排列的递归算法

    求字符串全排列的递归算法 void permutation(char * p_str, char * p_begin) { if(!p_str || !p_begin) { return; } if( ...

  3. 【字符串全排列】LeetCode 567. Permutation in String

    [字符串全排列]LeetCode 567. Permutation in String Solution1:[超时,未能AC] 得到s1的所有全排列组合,然后在s2中查找s1的全排列集合 因为超时,未 ...

  4. 字符串全排列算法_C#版_剑指OFFER

    字符串全排列算法_C#版_剑指OFFER 题目描述 ​题目描述 输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组. 例如输入字符串ABC,则输出由字符A, ...

  5. 【前端笔试】JavaScript实现字符串全排列

    我个人认为前端工程师笔试题中,算法题一般不难,也就这个难度,甚至比这还要简单.这是我在笔试过程中遇到的一个题~下面分享一下解题思路. 大体结构:定义一个方法,传入str变量,返回一个数组,包含所有排列 ...

  6. c++字符串全排列递归法

    网上关于字符串全排列的代码一大堆,总体而言分为递归法和非递归法两种实现.虽然递归法原理简单,代码简洁,但是我观察众多博客来看,没有把代码讲透,只有透过代码才能看清算法的本质. 问题:输入一字符串(要求 ...

  7. 28 字符串排列(还差点,list包含、Arrays、Collections的sort)全排列

    题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: 输 ...

  8. python打印字符串全排列_【算法15】字符串的全排列

    [题 目]输入一个字符串,打印该字符串的所有排列.例如输入字符串abc,输出其全排列为abc,acb,bac,bca,cab,cba. [思 路]我们想一下,如果不编程,手工做的话,我们的基本考虑是: ...

  9. 字符串全排列的问题 python和c语言实现

    前言 这是一个的经典的问题 设计一个算法,输出一个字符串字符的全排列. 比如,String = "abc" 输出是"abc","bac",& ...

  10. 求字符串全排列 python实现

    文章目录 算法思想 附上c语言实现 参考 算法思想 输入一个字符串,打印这个字符串中字符的全排列. eg: 输入:abc 输出:abc acb bac bca cab cba 思路:将求字符串的全排列 ...

最新文章

  1. opencv3 视频稳像
  2. t-sql使用小记2010-01-27
  3. Tensorlfow2.0 二分类和多分类focal loss实现和在文本分类任务效果评估
  4. MATLAB中unzip出错,node.js里unzip出错的处理
  5. pb 窗口数据修改sql_Snowflake将成为在云中变得更好的数据仓库
  6. 64位win10系统无法安装.Net framework3.5的两种解决方法
  7. linux安装mq报5724,linux下MQ简单配置手册.doc
  8. Linux上用户之间对话
  9. dos c语言显示符号图案,在DOS命令行窗口中显示出用各种字符拼凑出来的各种图案的实现方法,如本人头像...
  10. PointDSC: Robust Point Cloud Registration using Deep Spatial Consistency (PointDSC) 论文学习笔记小结
  11. 【转载】linux下如何使用sftp命令
  12. 在线EXCEL文件数据转换解析工具
  13. Cocos2d-x 坐标系及其坐标转换
  14. 数据层处理和性能优化
  15. 四大家族机器人资料免费送!赶快来下载
  16. lordPE转自http://blog.sina.com.cn/s/blog_6e8f83bc01014115.html
  17. 我用Python写了一个论文降重工具
  18. ceph 源代码分析 — peering 过程
  19. 云计算学习笔记——第四章 存储虚拟化
  20. UI设计—软件包装设计

热门文章

  1. Battery Charging Specification(BC1.2) 和 QC2.0 笔记
  2. Datagrip连接MySQL数据遇到com.mysql.cj.exceptions.InvalidConnectionAttributeException问题
  3. 非洲六个增速最快的经济体
  4. Pandas处理Excel超简单
  5. 【LeetCode刷题日记】栈类题目常见题型
  6. 微服务之「Cosul 服务注册与发现 」
  7. 403_交通数据综合分析实验
  8. iOS AppStore审核被拒To provide a link to a demo video
  9. 2021年中国移植HLA分型市场趋势报告、技术动态创新及2027年市场预测
  10. 东北人曾被北京驱逐?