《剑指Offer》读书笔记---面试题28:字符串的排列,(扩展:求字符串的所有组合)
2013-09-19 15:56
525 查看
题目:输入一个字符串,打印出字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。
书上的解法:
书上的解法,虽然可以打印出字符串的全排列,但是那些排列不是按字典序打印出来的,所以我用我以前经常用的类似位图的方法打印字典序的全排列。
本题扩展:
求n个字符,长度为m的所有组合。
书上提供的思路(不太怎么实现):
在求n个字符的长度为m(1 < m < n)的组合的时候,我们把这n个字符分成两部分:第一个字符和其余的所有字符。如果组合里包含第一个字符,则下一步在剩余的字符里选取m-1个字符;如果组合里不包含第一个字符,则下一步在剩余的n-1个字符里选取m个字符。也就是说,我们可以把求n个字符组成长度为m的组合的问题分解成两个子问题,分别求n-1个字符串中长度为m-1的组合,以及求n-1个字符的长度为m的组合。这两个子问题都 可以用递归的方式解决。
我的大概思路:
求n个字符,长度为m的所有组合。每一次递归从剩余的字符中正向选取一个字符,在递归返回后,再正向选取下一个字符,这样可以保证不会重复选择。
尚未解决的问题:
上述代码只有在输入的字符串的字符全不相同时才正确,否则的话会输出重复的组合。
书上的解法:
#include<cstdlib> #include<cstdio> #include<cstring> #include<stack> #include<vector> void Permutation( char *pStr ) ; void Permutation( char *pStr, char *pBegin ) ; void Permutation( char *pStr ) { if( NULL == pStr ) { return ; } Permutation( pStr , pStr) ; } void Permutation( char *pStr, char *pBegin ) { if( '\0' == *pBegin ) { printf("%s\n",pStr) ; } else { for(char *pCh = pBegin ; *pCh != '\0' ; ++pCh) { char temp = *pCh ; *pCh = *pBegin ; *pBegin = temp ; Permutation( pStr, pBegin + 1 ) ; temp = *pCh ; *pCh = *pBegin ; *pBegin = temp ; } } } int main(void) { freopen("in.txt","r",stdin) ; char szStr[100] ; while(scanf("%s",szStr) != EOF) { Permutation(szStr) ; printf("\n") ; } return 0 ; }
书上的解法,虽然可以打印出字符串的全排列,但是那些排列不是按字典序打印出来的,所以我用我以前经常用的类似位图的方法打印字典序的全排列。
#include<cstdlib> #include<cstdio> #include<cstring> #include<stack> #include<vector> const int N = 100 ; bool isUse ; void MyPermutation(const char *pszStr ) ; void MyPermutation(const char *pszStr ,int nIndex ,int nLen ,char *pszStore) ; void MyPermutation(const char *pszStr ) { if( NULL == pszStr) { return ; } int nLen = strlen(pszStr) ; char *pszStore = new char [ nLen + 1 ] ; MyPermutation( pszStr,0,nLen,pszStore ) ; delete [] pszStore ; } void MyPermutation( const char *pszStr , int nIndex ,int nLen ,char *pszStore ) { if( nIndex >= nLen ) { pszStore[nIndex] = '\0' ; printf("%s\n",pszStore) ; } else { for(int i = 0 ; i < nLen ; ++i) { if(false == isUse[i]) { isUse[i] = true ; pszStore[nIndex] = pszStr[i] ; MyPermutation(pszStr,nIndex+1,nLen,pszStore) ; isUse[i] = false ; } } } } int main(void) { freopen("in.txt","r",stdin) ; char szStr[100] ; while(scanf("%s",szStr) != EOF) { MyPermutation(szStr) ; printf("\n") ; } return 0 ; }
本题扩展:
求n个字符,长度为m的所有组合。
书上提供的思路(不太怎么实现):
在求n个字符的长度为m(1 < m < n)的组合的时候,我们把这n个字符分成两部分:第一个字符和其余的所有字符。如果组合里包含第一个字符,则下一步在剩余的字符里选取m-1个字符;如果组合里不包含第一个字符,则下一步在剩余的n-1个字符里选取m个字符。也就是说,我们可以把求n个字符组成长度为m的组合的问题分解成两个子问题,分别求n-1个字符串中长度为m-1的组合,以及求n-1个字符的长度为m的组合。这两个子问题都 可以用递归的方式解决。
我的大概思路:
求n个字符,长度为m的所有组合。每一次递归从剩余的字符中正向选取一个字符,在递归返回后,再正向选取下一个字符,这样可以保证不会重复选择。
#include<cstdlib> #include<cstdio> #include<cstring> #include<iostream> using std::endl ; using std::cout ; const int N = 100 ; void PrintCombination( char *pszStr ,int nCombinLen ) ; void PrintCombination( char *pszStr,int nStrLen ,char *pszCombination,int nNowLen , int nCombinLen ,int nBeginPos) ; void PrintCombination( char *pszStr,int nCombinLen ) { if( NULL == pszStr ) { return ; } int nLen = strlen(pszStr) ; char *szStore = new char[ nLen+1 ] ; for(int i = 1 ; i <= nCombinLen ; ++i ) { PrintCombination(pszStr,nLen,szStore,0,i,0) ; } } void PrintCombination( char *pszStr,int nStrLen,char *pszCombination,int nNowLen,int nCombinLen ,int nBeginPos ) { if( nNowLen >= nCombinLen ) { pszCombination[nNowLen] = '\0' ; printf( "%s\n",pszCombination ) ; } else { for(int i = nBeginPos ; i < nStrLen ; ++i) { pszCombination[nNowLen] = pszStr[i] ; PrintCombination( pszStr,nStrLen,pszCombination,nNowLen+1,nCombinLen,i+1) ; } } } int main(void) { freopen("in.txt","r",stdin) ; char szStr ; int m ; while(scanf("%s %d",szStr,&m) != EOF) { PrintCombination(szStr,m) ; printf("\n") ; } return 0 ; }
尚未解决的问题:
上述代码只有在输入的字符串的字符全不相同时才正确,否则的话会输出重复的组合。
相关文章推荐
- 剑指Offer中面试题28的扩展问题(求字符的所有组合)
- 剑指offer 面试题28 字符串的排列与集合的所有子集
- 剑指offer面试题28扩展提————字符串的组合
- 剑指Offer_面试题28.5_字符串的排列扩展_排列组合_八皇后问题
- (剑指Offer)面试题28:字符串的排列
- 《剑指Offer》面试题28:字符串的排列
- 剑指Offer系列-面试题28:字符串的排列
- 海涛老师的面试题-作业28-字符串的排列组合问题。
- 剑指Offer:面试题28——字符串的排列(java实现)(待序)
- 剑指Offer28字符串的排列(递归和非递归实现)扩展有重复元素的排列,字符串的组合种类
- 《剑指Offer》学习笔记--面试题28:字符串的排列
- 剑指offer面试题28:字符串的排列 Java实现
- 《剑指offer》面试题28:字符串的排列(牛客网版本) java
- 剑指Offer----面试题28----扩展:字符的所有组合
- 剑指offer之面试题28字符串的排列
- 剑指offer 面试题35扩展:从第一个字符串中删除第二个字符串中的所有字符 (C++版)
- 剑指Offer----面试题35:扩展----删除字符串中所有重复出现的字符 & 变位词
- 字符串的排列和组合实现(面试题 28)
- 剑指offer-面试题28-字符串的排列
- 剑指offer——面试题28:字符串的排列