問題:有乙個長度為 nlength 的字串 s,不考慮 s 裡面有相同的字元,將 s 中出現的字元排列成長度為 nlength 的字串,列印出所有的排列字串(包括原串)。
如,給定 abc ,則要輸出 abc,acb,bac,bca,cab,cba。
為了得到所有排列,我們採用首字元交換法,即,把後面的字元逐個與首字元交換,再把後面的字串當作乙個子問題,於是可以用遞迴解決,如圖1所示。
圖1遞迴解法
給出原始碼:
/*
輸入字串:inputword
每一次遞迴到最深層時組合形成的完整字串:outputword
要組合的字串的開始/結束位置:begin(inclusive) / end(exclusive)
*/void combineandshow(char *inputword,char *outputword,int begin,int end)
//原首字母不動 // 將 i = beging 的情況單獨處理是因為此時 firstch 和 currentch 是乙個變數的兩個引用
// 使用 a ^= b;b ^= a;a ^= b;的方法用於兩邊是同乙個變數時會有錯。
// 如 int a = 1; a ^= a; a ^= a; a ^= a; 這樣做會將 a 置為 0;
lastoutputch = firstch;
combineandshow(inputword,outputword,begin + 1,end);
lastoutputch = last_output_char;
*(outputword + begin + 1) = '\0';
for (int i = begin + 1;i != end - 1; ++ i) }
int main()
; //這裡不能用字串常量 : char *str = "12345678";
//因為後面的演算法會更改這個字串,所以要分配空間
char output[9] = ;
combineandshow(str,output,0,9);
return 0;
}
而一般情況下,遞迴的複雜度比動態規劃複雜度高不少,因為,遞迴呼叫有比較大的時間耗費,而且也會有很深的函式棧,耗費不少的記憶體空間。而迭代沒有函式遞迴呼叫的負擔,它儲存 i - 1 次計算結果並直接用於第 i 次的計算。 所以迭代的效率一般高於遞迴。我們把這個解決辦法換為迭代的。
為此,另外先寫了一篇文章,《
演算法之遞迴,迭代,動態規劃,分冶
》裡面歸納了遞迴與迭代的本質不同,既然知道不同,就知道如何去轉換了。在轉換為迭代的過程中,我們採用最簡單的轉換方法,從底向上迭代,將第 i- 1 輪的計算結果(設為 f(i-1))快取下來用於本輪(第 i 輪)構成結果 f(i)。
定義 i 為字串下標,設字串為 s,s[i] 表示取 s 的第 i 個字元。
f(0) 表示字串為 s[0] 組合的結果,
f(1) 表示字串為 s[0],s[1] 組合的結果,
f(2) 表示字串為 s[0],s[1],s[2]組合的結果,
f(3) 表示字串為 s[0],s[1],s[2],s[3] 組合的結果,
每乙個 f 都是乙個集合(也可以稱為字串陣列)。
模擬由 f(2) 得到 f(3):
1.對於 f(2) 中的每乙個字串 t 有以下步驟2:
2.將 s[3] 追加到 t 的末尾。新得到的 t 為 t'。對 t' 有步驟3
3.遍歷 t' 的每乙個字元,將它與 t' 最末尾的字元交換。每次交換得到乙個新字串加入 f(3)
經過這三步,便能求出 f(3)。
其實這種轉換是不節實際的,因為這需要很大的空間來存放結果。
字母全排列
1.字母全排列 2.3.首先可以看出,全排列其實就是階乘,3個字母會有3階乘種表現,4字母會有4階乘種 4.上面fat的變化是有規律的 我們要得到全排列的做法是 將三個字母分別作為開頭,然後 5.調整除了第乙個字元之外的位置,即fat 將後兩個調整 fta 6.當有4個字母時,如golf,那麼分別讓...
字母大小全排列
題目描述 給定乙個字串s,通過將字串s中的每個字母轉變大小寫,我們可以獲得乙個新的字串。輸出所有可能的字串的數量。輸入測試樣例由多組測試資料組成,每組測試資料第一行輸入乙個字串s 1 s.length 12 輸出輸出所有可能的字串的數量 樣例輸入 copy q1b2 樣例輸出 copy 4第一種方法...
1013 字母排列
時間限制 10 sec 記憶體限制 128 mb 提交 247 解決 148 提交 狀態 討論版 編寫乙個程式,當輸入不超過200個字元組成的英文文字時,計算機將這個句子中的字母按英文本典字母順序重新排列,排列後的單詞的長度要與原始句子中的長度 相同。例如 輸入 輸出 並且要求只對 到 的字母重新排...