擅長排列的小明
時間限制:1000 ms | 記憶體限制:65535 KB
難度:4
- 描述
- 小明十分聰明,而且十分擅長排列計算。比如給小明一個數字5,他能立刻給出1-5按字典序的全排列,如果你想為難他,在這5個數字中選出幾個數字讓他繼續全排列,那麼你就錯了,他同樣的很擅長。現在需要你寫一個程式來驗證擅長排列的小明到底對不對。
- 輸入
- 第一行輸入整數N(1<N<10)表示多少組測試資料,
每組測試資料第一行兩個整數 n m (1<n<9,0<m<=n) - 輸出
- 在1-n中選取m個字元進行全排列,按字典序全部輸出,每種排列佔一行,每組資料間不需分界。如樣例
- 樣例輸入
-
2 3 1 4 2
- 樣例輸出
-
1 2 3 12 13 14 21 23 24 31 32 34 41 42 43
題目就是求字串123..n的全排列的前m個字元,將123..n進行全排列,每個排列的前m個字元即為所求,注意重複的字元#include <iostream> #include <string> #include <set> #include <algorithm> #include <iterator> using namespace std; int main(){ int N; cin >>N; while(N--){ int n,m; cin >> n >> m; string str = ""; for(int i = 0 ; i < n; ++i) str+='1'+i; set<string> res; do{ string tmp = str.substr(0,m); if(res.find(tmp)==res.end()) res.insert(tmp); }while(next_permutation(str.begin(),str.end())); copy(res.begin(),res.end(),ostream_iterator<string>(cout,"\n")); } }
對其空間複雜度優化,不需要用set儲存每個排列,只需記住前一個排列,如果現在排列不等於前一個排列才輸出,利用next_permutation函式時按照字串大小輸出的
優化後的程式碼
#include <iostream> #include <string> #include <algorithm> using namespace std; int main(){ int N; cin >>N; while(N--){ int n,m; cin >> n >> m; string str = "",preStr=""; for(int i = 0 ; i < n; ++i) str+='1'+i; do{ string tmp = str.substr(0,m); if(preStr!=tmp){ preStr = tmp; cout<<preStr<<endl; } }while(next_permutation(str.begin(),str.end())); } }