排列组合之字符串的全排列和组合算法

信息学奥赛一本通C++语言——1199:全排列 【题目描述】 给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。 我们假设对于小写字母有‘a’ <‘b’ < … <‘y’<‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。 【输入】 只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。 【输出】 输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字... 阅读详情

 

全排列在笔试面试中很热门,因为它难度适中,既可以考察递归实现,又能进一步考察非递归的实现,便于区分出考生的水平。所以在百度和迅雷的校园招聘以及程序员和软件设计师的考试中都考到了,因此本文对全排列作下总结帮助大家更好的学习和理解。对本文有任何补充之处,欢迎大家指出。
首先来看看题目是如何要求的(百度迅雷校招笔试题)。
一、字符串的排列
用C++写一个函数, 如 Foo(const char *str), 打印出 str 的全排列,
如 abc 的全排列: abc, acb, bca, dac, cab, cba

一、全排列的递归实现

为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。找到这个规律后,递归的代码就很容易写出来了:

  1. #include<iostream>  
  2. using namespace std; 
  3. #include<assert.h>  
  4.  
  5. void Permutation(char* pStr,char* pBegin) 
  6. { 
  7.     assert(pStr && pBegin); 
  8.  
  9.     if(*pBegin =='\0') 
  10.         printf("%s\n",pStr); 
  11.     else 
  12.     { 
  13.         for(char* pCh = pBegin; *pCh !='\0'; pCh++) 
  14.         { 
  15.             swap(*pBegin,*pCh); 
  16.             Permutation(pStr, pBegin+1); 
  17.             swap(*pBegin,*pCh); 
  18.         } 
  19.     } 
  20. } 
  21.  
  22. int main(void) 
  23. { 
  24.     char str[] = "abc"; 
  25.     Permutation(str,str); 
  26.     return 0; 
  27. } 
  1. #include<iostream> 
  2. using namespace std; 
  3. #include<assert.h> 
  4.  
  5. void Permutation(char* pStr,char* pBegin) 
  6. { 
  7.     assert(pStr && pBegin); 
  8.  
  9.     if(*pBegin == '\0') 
  10.         printf("%s\n",pStr); 
  11.     else 
  12.     { 
  13.         for(char* pCh = pBegin; *pCh !='\0'; pCh++) 
  14.         { 
  15.             swap(*pBegin,*pCh); 
  16.             Permutation(pStr, pBegin+1); 
  17.             swap(*pBegin,*pCh); 
  18.         } 
  19.     } 
  20. } 
  21.  
  22. int main(void) 
  23. { 
  24.     char str[] = "abc"; 
  25.     Permutation(str,str); 
  26.     return 0; 
  27. } 

另外一种写法:

  1. //k表示当前选取到第几个数,m表示共有多少个数  
  2. void Permutation(char* pStr,int k,int m) 
  3. { 
  4.     assert(pStr); 
  5.  
  6.     if(k == m) 
  7.     { 
  8.         static int num = 1; //局部静态变量,用来统计全排列的个数 
  9.         printf("第%d个排列\t%s\n",num++,pStr); 
  10.     } 
  11.     else 
  12.     { 
  13.         for(int i = k; i <= m; i++) 
  14.         { 
  15.             swap(*(pStr+k),*(pStr+i)); 
  16.             Permutation(pStr, k + 1 , m); 
  17.             swap(*(pStr+k),*(pStr+i)); 
  18.         } 
  19.     } 
  20. } 
  21.  
  22. int main(void) 
  23. { 
  24.     char str[] = "abc"; 
  25.     Permutation(str , 0 , strlen(str)-1); 
  26.     return 0; 
  27. } 
  1. //k表示当前选取到第几个数,m表示共有多少个数 
  2. void Permutation(char* pStr,int k,int m) 
  3. { 
  4.     assert(pStr); 
  5.  
  6.     if(k == m) 
  7.     { 
  8.         static int num = 1; //局部静态变量,用来统计全排列的个数 
  9.         printf("第%d个排列\t%s\n",num++,pStr); 
  10.     } 
  11.     else 
  12.     { 
  13.         for(int i = k; i <= m; i++) 
  14.         { 
  15.             swap(*(pStr+k),*(pStr+i)); 
  16.             Permutation(pStr, k + 1 , m); 
  17.             swap(*(pStr+k),*(pStr+i)); 
  18.         } 
  19.     } 
  20. } 
  21.  
  22. int main(void) 
  23. { 
  24.     char str[] = "abc"; 
  25.     Permutation(str , 0 , strlen(str)-1); 
  26.     return 0; 
  27. } 
如果字符串中有重复字符的话,上面的那个方法肯定不会符合要求的,因此现在要想办法来去掉重复的数列。
二、去掉重复的全排列的递归实现
由于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数与第三个数是不相同的,交换之后得到221。与由122中第一个数与第三个数交换所得的221重复了。所以这个方法不行。

换种思维,对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。下面给出完整代码:

  1. #include<iostream>  
  2. using namespace std; 
  3. #include<assert.h>  
  4.  
  5. //在[nBegin,nEnd)区间中是否有字符与下标为pEnd的字符相等 
  6. bool IsSwap(char* pBegin ,char* pEnd) 
  7. { 
  8.     char *p; 
  9.     for(p = pBegin ; p < pEnd ; p++) 
  10.     { 
  11.         if(*p == *pEnd) 
  12.             return false; 
  13.     } 
  14.     return true; 
  15. } 
  16. void Permutation(char* pStr ,char *pBegin) 
  17. { 
  18.     assert(pStr); 
  19.  
  20.     if(*pBegin == '\0') 
  21.     { 
  22.         static int num = 1; //局部静态变量,用来统计全排列的个数 
  23.         printf("第%d个排列\t%s\n",num++,pStr); 
  24.     } 
  25.     else 
  26.     { 
  27.         for(char *pCh = pBegin; *pCh !='\0'; pCh++)  //第pBegin个数分别与它后面的数字交换就能得到新的排列   
  28.         { 
  29.             if(IsSwap(pBegin , pCh)) 
  30.             { 
  31.                 swap(*pBegin , *pCh); 
  32.                 Permutation(pStr , pBegin + 1); 
  33.                 swap(*pBegin , *pCh); 
  34.             } 
  35.         } 
  36.     } 
  37. } 
  38.  
  39. int main(void) 
  40. { 
  41.     char str[] ="baa"; 
  42.     Permutation(str , str); 
  43.     return 0; 
  44. } 
  1. #include<iostream> 
  2. using namespace std; 
  3. #include<assert.h> 
  4.  
  5. //在[nBegin,nEnd)区间中是否有字符与下标为pEnd的字符相等 
  6. bool IsSwap(char* pBegin ,char* pEnd) 
  7. { 
  8.     char *p; 
  9.     for(p = pBegin ; p < pEnd ; p++) 
  10.     { 
  11.         if(*p == *pEnd) 
  12.             return false; 
  13.     } 
  14.     return true; 
  15. } 
  16. void Permutation(char* pStr ,char *pBegin) 
  17. { 
  18.     assert(pStr); 
  19.  
  20.     if(*pBegin == '\0') 
  21.     { 
  22.         static int num = 1; //局部静态变量,用来统计全排列的个数 
  23.         printf("第%d个排列\t%s\n",num++,pStr); 
  24.     } 
  25.     else 
  26.     { 
  27.         for(char *pCh = pBegin; *pCh !='\0'; pCh++)  //第pBegin个数分别与它后面的数字交换就能得到新的排列   
  28.         { 
  29.             if(IsSwap(pBegin , pCh)) 
  30.             { 
  31.                 swap(*pBegin , *pCh); 
  32.                 Permutation(pStr , pBegin + 1); 
  33.                 swap(*pBegin , *pCh); 
  34.             } 
  35.         } 
  36.     } 
  37. } 
  38.  
  39. int main(void) 
  40. { 
  41.     char str[] = "baa"; 
  42.     Permutation(str , str); 
  43.     return 0; 
  44. } 
OK,到现在我们已经能熟练写出递归的方法了,并且考虑了字符串中的重复数据可能引发的重复数列问题。那么如何使用非递归的方法来得到全排列了?

三、全排列的非递归实现
要考虑全排列的非递归实现,先来考虑如何计算字符串的下一个排列。如"1234"的下一个排列就是"1243"。只要对字符串反复求出下一个排列,全排列的也就迎刃而解了。
如何计算字符串的下一个排列了?来考虑"926520"这个字符串,我们从后向前找第一双相邻的递增数字,"20"、"52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后面找一个比替换数大的最小数(这个数必然存在),0、2都不行,5可以,将5和2交换得到"956220",然后再将替换点后的字符串"6220"颠倒即得到"950226"。
对于像“4321”这种已经是最“大”的排列,采用STL中的处理方法,将字符串整个颠倒得到最“小”的排列"1234"并返回false。

这样,只要一个循环再加上计算字符串下一个排列的函数就可以轻松的实现非递归的全排列算法。按上面思路并参考STL中的实现源码,不难写成一份质量较高的代码。值得注意的是在循环前要对字符串排序下,可以自己写快速排序的代码(请参阅《白话经典算法之六 快速排序 快速搞定》),也可以直接使用VC库中的快速排序函数(请参阅《使用VC库函数中的快速排序函数》)。下面列出完整代码:

  1. #include<iostream>  
  2. #include<algorithm>  
  3. #include<cstring>  
  4. using namespace std; 
  5. #include<assert.h>  
  6.  
  7. //反转区间  
  8. void Reverse(char* pBegin ,char* pEnd) 
  9. { 
  10.     while(pBegin < pEnd) 
  11.         swap(*pBegin++ , *pEnd--); 
  12. } 
  13. //下一个排列  
  14. bool Next_permutation(char a[]) 
  15. { 
  16.     assert(a); 
  17.     char *p , *q , *pFind; 
  18.     char *pEnd = a + strlen(a) - 1; 
  19.     if(a == pEnd) 
  20.         return false; 
  21.     p = pEnd; 
  22.     while(p != a) 
  23.     { 
  24.         q = p; 
  25.         p--; 
  26.         if(*p < *q)  //找降序的相邻2数,前一个数即替换数  
  27.         { 
  28.              //从后向前找比替换点大的第一个数  
  29.             pFind = pEnd; 
  30.             while(*pFind < *p) 
  31.                 --pFind; 
  32.             swap(*p , *pFind); 
  33.             //替换点后的数全部反转  
  34.             Reverse(q , pEnd); 
  35.             returntrue; 
  36.         } 
  37.     } 
  38.     Reverse(a , pEnd);   //如果没有下一个排列,全部反转后返回false   
  39.     return false; 
  40. } 
  41.  
  42. int cmp(constvoid *a,constvoid *b) 
  43. { 
  44.     return int(*(char *)a - *(char *)b); 
  45. } 
  46. int main(void) 
  47. { 
  48.     char str[] = "bac"; 
  49.     int num = 1; 
  50.     qsort(str , strlen(str),sizeof(char),cmp); 
  51.     do 
  52.     { 
  53.         printf("第%d个排列\t%s\n",num++,str);  
  54.     }while(Next_permutation(str)); 
  55.     return 0; 
  56. } 
  1. #include<iostream> 
  2. #include<algorithm> 
  3. #include<cstring> 
  4. using namespace std; 
  5. #include<assert.h> 
  6.  
  7. //反转区间 
  8. void Reverse(char* pBegin ,char* pEnd) 
  9. { 
  10.     while(pBegin < pEnd) 
  11.         swap(*pBegin++ , *pEnd--); 
  12. } 
  13. //下一个排列 
  14. bool Next_permutation(char a[]) 
  15. { 
  16.     assert(a); 
  17.     char *p , *q , *pFind; 
  18.     char *pEnd = a + strlen(a) - 1; 
  19.     if(a == pEnd) 
  20.         return false; 
  21.     p = pEnd; 
  22.     while(p != a) 
  23.     { 
  24.         q = p; 
  25.         p--; 
  26.         if(*p < *q)  //找降序的相邻2数,前一个数即替换数  
  27.         { 
  28.              //从后向前找比替换点大的第一个数 
  29.             pFind = pEnd; 
  30.             while(*pFind < *p) 
  31.                 --pFind; 
  32.             swap(*p , *pFind); 
  33.             //替换点后的数全部反转 
  34.             Reverse(q , pEnd); 
  35.             return true; 
  36.         } 
  37.     } 
  38.     Reverse(a , pEnd);   //如果没有下一个排列,全部反转后返回false   
  39.     return false; 
  40. } 
  41.  
  42. int cmp(constvoid *a,constvoid *b) 
  43. { 
  44.     return int(*(char *)a - *(char *)b); 
  45. } 
  46. int main(void) 
  47. { 
  48.     char str[] = "bac"; 
  49.     int num = 1; 
  50.     qsort(str , strlen(str),sizeof(char),cmp); 
  51.     do 
  52.     { 
  53.         printf("第%d个排列\t%s\n",num++,str);  
  54.     }while(Next_permutation(str)); 
  55.     return 0; 
  56. } 
至此我们已经运用了递归与非递归的方法解决了全排列问题,总结一下就是:
1、全排列就是从第一个数字起每个数分别与它后面的数字交换。
2、去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。
3、全排列的非递归就是由后向前找替换数和替换点,然后由后向前找第一个比替换数大的数与替换数交换,最后颠倒替换点后的所有数据。

二、字符串的组合

题目:输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。

上面我们详细讨论了如何用递归的思路求字符串的排列。同样,本题也可以用递归的思路来求字符串的组合。

假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:第一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;第二是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。下面是这种思路的参考代码:
  1. #include<iostream>  
  2. #include<vector>  
  3. #include<cstring>  
  4. using namespace std; 
  5. #include<assert.h>  
  6.  
  7. void Combination(char *string ,int number,vector<char> &result); 
  8.  
  9. void Combination(char *string) 
  10. { 
  11.     assert(string != NULL); 
  12.     vector<char> result; 
  13.     int i , length = strlen(string); 
  14.     for(i = 1 ; i <= length ; ++i) 
  15.         Combination(string , i ,result); 
  16. } 
  17.  
  18. void Combination(char *string ,int number , vector<char> &result) 
  19. { 
  20.     assert(string != NULL); 
  21.     if(number == 0) 
  22.     { 
  23.         static int num = 1; 
  24.         printf("第%d个组合\t",num++); 
  25.  
  26.         vector<char>::iterator iter = result.begin(); 
  27.         for( ; iter != result.end() ; ++iter) 
  28.             printf("%c",*iter); 
  29.         printf("\n"); 
  30.         return ; 
  31.     } 
  32.     if(*string == '\0') 
  33.         return ; 
  34.     result.push_back(*string); 
  35.     Combination(string + 1 , number - 1 , result); 
  36.     result.pop_back(); 
  37.     Combination(string + 1 , number , result); 
  38. } 
  39.  
  40. int main(void) 
  41. { 
  42.     char str[] = "abc"; 
  43.     Combination(str); 
  44.     return 0; 
  45. } 
  1. #include<iostream> 
  2. #include<vector> 
  3. #include<cstring> 
  4. using namespace std; 
  5. #include<assert.h> 
  6.  
  7. void Combination(char *string ,int number,vector<char> &result); 
  8.  
  9. void Combination(char *string) 
  10. { 
  11.     assert(string != NULL); 
  12.     vector<char> result; 
  13.     int i , length = strlen(string); 
  14.     for(i = 1 ; i <= length ; ++i) 
  15.         Combination(string , i ,result); 
  16. } 
  17.  
  18. void Combination(char *string ,int number , vector<char> &result) 
  19. { 
  20.     assert(string != NULL); 
  21.     if(number == 0) 
  22.     { 
  23.         static int num = 1; 
  24.         printf("第%d个组合\t",num++); 
  25.  
  26.         vector<char>::iterator iter = result.begin(); 
  27.         for( ; iter != result.end() ; ++iter) 
  28.             printf("%c",*iter); 
  29.         printf("\n"); 
  30.         return ; 
  31.     } 
  32.     if(*string == '\0') 
  33.         return ; 
  34.     result.push_back(*string); 
  35.     Combination(string + 1 , number - 1 , result); 
  36.     result.pop_back(); 
  37.     Combination(string + 1 , number , result); 
  38. } 
  39.  
  40. int main(void) 
  41. { 
  42.     char str[] = "abc"; 
  43.     Combination(str); 
  44.     return 0; 
  45. } 

由于组合可以是1个字符的组合,2个字符的字符……一直到n个字符的组合,因此在函数void Combination(char* string),我们需要一个for循环。另外,我们一个vector来存放选择放进组合里的字符。

字符串全排列扩展----八皇后问题
    题目:在8×8的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后不得处在同一行、同一列或者同一对角斜线上。下图中的每个黑色格子表示一个皇后,这就是一种符合条件的摆放方法。请求出总共有多少种摆法。


    这就是有名的八皇后问题。解决这个问题通常需要用递归,而递归对编程能力的要求比较高。因此有不少面试官青睐这个题目,用来考察应聘者的分析复杂问题的能力以及编程的能力。

由于八个皇后的任意两个不能处在同一行,那么这肯定是每一个皇后占据一行。于是我们可以定义一个数组ColumnIndex[8],数组中第i个数字表示位于第i行的皇后的列号。先把ColumnIndex的八个数字分别用0-7初始化,接下来我们要做的事情就是对数组ColumnIndex做全排列。由于我们是用不同的数字初始化数组中的数字,因此任意两个皇后肯定不同列。我们只需要判断得到的每一个排列对应的八个皇后是不是在同一对角斜线上,也就是数组的两个下标i和j,是不是i-j==ColumnIndex[i]-Column[j]或者j-i==ColumnIndex[i]-ColumnIndex[j]。

关于排列的详细讨论,详见上面的讲解。
接下来就是写代码了。思路想清楚之后,编码并不是很难的事情。下面是一段参考代码:

  1. #include<iostream>  
  2. using namespace std; 
  3.  
  4. int g_number = 0; 
  5. void Permutation(int * ,int  ,int ); 
  6. void Print(int * ,int ); 
  7.  
  8. void EightQueen( ) 
  9. { 
  10.     const int queens = 8; 
  11.     int ColumnIndex[queens]; 
  12.     for(int i = 0 ; i < queens ; ++i) 
  13.         ColumnIndex[i] = i;    //初始化 
  14.     Permutation(ColumnIndex , queens , 0); 
  15. } 
  16.  
  17. bool Check(int ColumnIndex[] ,int length) 
  18. { 
  19.     int i,j; 
  20.     for(i = 0 ; i < length; ++i) 
  21.     { 
  22.         for(j = i + 1 ; j < length; ++j) 
  23.         { 
  24.             if( i - j == ColumnIndex[i] - ColumnIndex[j] || j - i == ColumnIndex[i] - ColumnIndex[j])  //在正、副对角线上 
  25.                 returnfalse; 
  26.         } 
  27.     } 
  28.     return true; 
  29. } 
  30. void Permutation(int ColumnIndex[] ,int length ,int index) 
  31. { 
  32.     if(index == length) 
  33.     { 
  34.         if( Check(ColumnIndex , length) )  //检测棋盘当前的状态是否合法 
  35.         { 
  36.             ++g_number; 
  37.             Print(ColumnIndex , length); 
  38.         } 
  39.     } 
  40.     else 
  41.     { 
  42.         for(int i = index ; i < length; ++i)  //全排列 
  43.         { 
  44.             swap(ColumnIndex[index] , ColumnIndex[i]); 
  45.             Permutation(ColumnIndex , length , index + 1); 
  46.             swap(ColumnIndex[index] , ColumnIndex[i]); 
  47.         } 
  48.     } 
  49. } 
  50.  
  51. void Print(int ColumnIndex[] ,int length) 
  52. { 
  53.     printf("%d\n",g_number); 
  54.     for(int i = 0 ; i < length; ++i) 
  55.         printf("%d ",ColumnIndex[i]); 
  56.     printf("\n"); 
  57. } 
  58.  
  59. int main(void) 
  60. { 
  61.     EightQueen(); 
  62.     return 0; 
  63. } 

原帖:http://blog.youkuaiyun.com/zz198808/article/details/7657168

C++字符串全排列(递归法)和(迭代法)以及next_permutation底层原理详解 阅读详情

相关推荐

一本通的递归练习

递归练习 1199:全排列 给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。 我们假设对于小写字母有‘a’ &amp;lt;‘b’ &amp;lt; … &amp;lt;‘y’&amp;lt;‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。 char a[10],b[10];//将a字符串的各种排列依次放到b字符串中 int vis[10],n;//用vis[i]来代表a[i]字母有没有被访问过 v...

flymist的博客 554

字符串的全排列

题目描述 输入一个字符串,打印出该字符串中字符的所有排列。 例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串 abc、acb、bac、bca、cab 和 cba。 分析与解法 解法一、递归实现 从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如此递归处理,从而得到所有元素的全排列。以对字符串abc进行全排列为例,我们可以这么做:以abc为例 固定...

qq_43324779的博客 5115

算法题解:给定一个字符串输出其全排列形式的所有字符串(JAVA代码)

算法题解:给定一个字符串输出其全排列形式的所有字符串(JAVA代码) 例如:给定字符串:ABC,输出结果有6种: ABC ACB BAC BCA CBA CAB 问题分析 这个问题可以采用递归算法求解。 首先看下图所示: 给定的字符串包含ABC三个字符,从第1个字符A开始,分别用A与第2个位置上的B交换,用A与第3个位置上的C交换,可以得到3种不同的结果:ABC,BAC,CBA。 然...

梅森上校的博客 业精于勤荒于嬉,形成于思毁于随。 3094

【算法基础】字符串的全排列算法

题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 输入描述 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。 这道题是剑指offfer中一道经典的题,如果有n个元素,我们就能有n*(n - 1)个全排列,n为1时,只有一个全排列 举...

Qregi的博客 4905

字符串排列(全排列)

题目描述 编写一个方法,确定某字符串的所有排列组合。 给定一个stringA和一个intn,代表字符串和其长度,请返回所有该字符串字符的排列,保证字符串长度小于等于11且字符串中字符均为大写英文字符,排列中的字符串按字典序从大到小排序。(不合并重复字符串) 测试样例: "ABC" 返回:["CBA","CAB","BCA","BAC","ACB","ABC"] Solution...

夏洛克福尔摩斯 1537

word2vector入门教程

摘要: 网上已经有许多对w2v的介绍了,这里只是做一个简单的概括。下面这篇文章我认为是关于W2V写的比较好的文章,读者有兴趣可以先参考一下: w2v参考文章1 另外一篇是关于Skip-Gram和CBow的介绍。 Skip-Gram&CBOW 逻辑比较清晰的综述文章: 综述文章 数学原理很清晰很短的一篇文章(也有关于负采样的简单说明) 参考文章 1.什么

SCUT_Sam 1万+

排列组合算法总结(含Java实现)

一. 排列组合1. 排列(1)排列:(2)全排列:2. 组合:从n个元素中选择m个元素(不考虑顺序)

Wendy0719的博客 1万+

通达信指标加密DLL加密解密三个公式源码准确率90%以上超级指标精准买卖绝世指标

通达信指标加密DLL加密解密三个公式源码准确率90%以上超级指标精准买卖绝世指标 1 超级指标 指标公式:买卖提示非常明显(适合通达信) 指标源码如下: M:3 100 60 N 3 100 30 散户线: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M));RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100; K:=SMA(RSV,5,1); D:=SMA(K,3,1); J:=3*K-2*D;主力

m0_60244077的博客 3万+

字符串全排列

字符串的全排列 问题描述: 给定一个长度为n的字符串,要求输出该字符串的所有字符的所有排列情况,比如给出字符串“abc”,则所有的排列情况为“abc”、“acb”、“bac”、“bca”、“cab”、“cba”。 思路: 首先将字符串s分解为一个等长的字符组ns,每个ns[i]存储一个字符,所以问题实际求的是字符组ns的全排列问题。以字符串“abc”为例,我们可以将其分为两个部分:a和bc,即第一...

早早踏入养生行列 544

Unified Access Control:从NAS到RRC的5G接入控制全流程解析

本文深入解析了5G统一接入控制(Unified Access Control)的全流程,从NAS到RRC的协同工作机制。通过身份核验、业务分类和动态决策三个核心步骤,UAC实现了智能调度和弹性决策,确保海量设备接入时的网络稳定性。文章详细介绍了USIM卡的身份凭证体系、NAS层的业务分类引擎以及RRC层的动态决策机制,并提供了实战案例和常见问题排查方法。

weixin_30855099的博客 587

【CVPR 2025】清华:注意力状态空间模块,Mamba与注意力的超强组合,即插即用!

MambaIRv2提出了一种创新的图像恢复模型,通过引入注意力状态空间模块(ASSM)解决了Mamba模型因果建模限制问题。该模型结合语义引导邻域机制和注意力状态空间方程,实现了非因果建模,有效缓解了长距离衰减问题。实验表明,MambaIRv2在图像超分辨率、JPEG压缩伪影减少和图像去噪等任务中表现优异,参数更少但性能超越现有方法。

qq_43303160的博客 3039

php全排列

字符串全排列(递归) function permutationStr($str, $tmp = '') { $length = strlen($str); if($length <= 1){ echo $str.$tmp."\n"; }else{ for ($i=0; $i < $length; $i++) { /* $flag = false;//去除重复 ...

zhuzi121121的博客 478

数字滤波器应用介绍

线性滤波器FIR ,会引起恒定延迟,通过补零的方式补偿非线性滤波器IIR,会引起频率相关的延迟,通过零相位延迟filtfilt补偿从信号中去除不需要的频谱时,通过滤波和补偿实现。如果需要去除的频率与采样率相差甚远,比如4kHz 与100Hz, 可通过 低通滤波->补偿->降采样–> 滤波 补偿 -->上采样还原的方法。*降采样前一定要先低通滤波为了防止混叠。

weixin_39107270的博客 274

递归算法之全排列生成(Permutations)详细解读

全排列(Permutations)是指从给定的 𝑛个元素中,按照某种顺序进行排列,生成所有可能的顺序组合。全排列是排列组合中的一个重要问题,在算法、数学、以及计算机科学中有着广泛的应用。

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 3130

Python从0到100(一):初识Python及安装Pycharm

Python从0到100(一):初识Python及安装Pycharm。Python是由荷兰人吉多·范罗苏姆(Guido von Rossum)发明的一种编程语言,是目前世界上最受欢迎和拥有最多用户群体的编程语言。

拥有百余位万粉技术博主、200余位可合作代发博主,私域技术社群规模达千人,商务合作私信 8万+

2ED2410-EM的使用

2ED2410-EM的使用

让你爱上电路设计 969

给定一个字符串,输出所有的排列组合方式

去参加一个笔试,遇到一个问题就是给定字符串"123456"要我写程序输出所有的排列组合方式,当时头很大,一直想不出来,于是很磋的写了循环。回来了好好想了想,参考网上的资料,今天真正理解并且自己写了出来。是用递归,理解为每次都是求已知的字符串与未排列的字符串的组合! /* 2

5490

uniapp [全端兼容] - 详细实现拍照或相册选取图片后插入水印功能,手机拍照或相册上传图像并添加自定义水印及指定位置显示水印,uniApp给图片加水印后上传到后端服务器或保存到本机相册详细教程!

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,图片水印,上传照片带水印,从相册选择图片加水印功能,拍完照片给图片加水印,添加照片水印,uniapp图片加水印,为图片添加自定义水印,uni-app上传图片并添加水印,上传图片加水印,uni-app如何对拍摄的照片加水印,uni-app实现图片上传添加水印操作,给上传的图片添加上水印,图片加完水印后如何上传到服务器,水印相机,拍照图片加水印,相册选取后给图片加上水印,渲染失败,无法保存,文字水印,日期

🏆 前端领域优质创作者 1万+

java字符串组合_Java实现abc字符串排列组合

1.可重复排列:abc三个字符组成的所有长度为3的字符串,aaa,aab,aac......ccc 一共27种利用递归的思想,第一个字符可以从abc中选择一个,三种选择,之后问题转化为abc组成长度为2的字符的情况,循环递归后可以求出所有的可能。控制好循环退出条件即可。利用递归可以处理,不知道字符长度的情况下,即通用处理。如果知道长度,只需要利用多层循环,也可以得出结论。public class ...

weixin_42528191的博客 3000

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

全排列和组合的实现算法

一 全排列算法原理和实现 全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。现以{1, 2, 3, 4, 5}为例说明如何编写全排列的递归算法。 1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。由于一个数的全排列就是其本身,从而得到以上结果。 2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3

tianmo2010的专栏 2351

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

算法 - 输出一个字符串的全排列(C++)

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net /* * Created by Chimomo * * 实现方法: * 对于一个字符串"abc"输出它的全排列,第一个字符应该分别为a,b,c;第二个字符,后面应该是除去已输出部分的剩余部分的全排列。 * * 即对于"abc", *...

了解➔熟悉➔掌握➔精通 6万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

输出一个字符串的全排列

代码: # using python3 不考虑有重复的 def permutation(str, begin, length): if begin == (length - 1): # print("print: begin:%d length:%d" % (begin,length)) print(str) #输出一个字符串的全排列 ...

Oliver King 的小窝 1139

java 字符串排列组合_java实现字符串排列组合问题

本文为大家介绍了java实现字符串排列组合问题,供大家参考,具体内容如下import java.util.ArrayList;import java.util.Collections;/*** 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,* bca,cab和cba。** @author pom...

weixin_39946274的博客 640
上一篇: 离散数学之鸽巢原理
下一篇: 加密算法总结
crazyhacking
博客等级 码龄15年 299粉丝 148原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值