全排列在筆試面試中很熱門,因為它難度適中,既可以考察遞歸實現,又能進一步考察非遞歸的實現,便於區分出考生的水平。所以在百度和迅雷的校園招聘以及程序員和軟件設計師的考試中都考到了,因此本文對全排列作下總結幫助大家更好的學習和理解。對本文有任何補充之處,歡迎大家指出。
首先來看看題目是如何要求的(百度迅雷校招筆試題)。
用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。因此可以知道——全排列就是從第一個數字起每個數分別與它後面的數字交換。
#includeusing namespace std; int n = 0; void cout1(int list[]) { for (int c = 0; c<=1; c++) { printf("%d ", list[c]); } printf("\n"); } void swap(int *a, int *b) { int m; m = *a; *a = *b; *b = m; } void perm(int list[], int k, int m) { int i; if(k > m) //k=0 m=1 ---1 :k =1: k=2: { for(i = 0; i <= m; i++) printf("%d ", list[i]); printf("\n"); n++; } else { for(i = k; i <= m; i++) //k=0,m=1 --1 :k =i =1: { swap(&list[k], &list[i]); // cout1(list); perm(list, k + 1, m); //m =k =1: //1 swap(&list[k], &list[i]); } } } int main() { int list[] = {1, 2,3 }; perm(list, 0, 2); printf("total:%d\n", n); system("pause"); return 0; }
運行效果如下:
OK !請細細的Debug,是不是有新的發現呢?如果我全改成相同的,又會有什麼發現呢?改成222哈!
運行效果如下:
先消化那麼多吧,下面我將去掉重復的全排列的遞歸實現和使用全排列的非遞歸實現!
(如果您有更有效率的算法請您與我們共同分享!)
期待將持續更新!