給定一個正整數 n ,輸出外觀數列的第 n 項。
「外觀數列」是一個整數序列,從數字 1 開始,序列中的每一項都是對前一項的描述。
你可以將其視為由遞歸公式定義的數字字串序列:
countAndSay(1) = "1"
countAndSay(n)是對countAndSay(n-1) 的描述,然後轉換成另一個數字字串。
前五項如下:
1、1 —— 第一項是數字1
2、11 —— 描述前一項,這個數是1 即“ 一個1 ”,記作"11"
3、21 —— 描述前一項,這個數是11 即「 二個1 」 ,記作"21"
4、1211 —— 描述前一項,這個數是21 即「 一個2一個1 」 ,記作"1211"
5、111221 —— 描述前一項,這個數是1211 即「 一個1 一個2 二個1 」 ,記作"111221"
所謂的「外觀數列」,其實本質上只是依序統計字串中連續相同字元的個數。
題目中給定的遞歸公式定義的數字字串序列如下:
countAndSay(1) = "1";
countAndSay(n) 是對countAndSay(n-1) 的描述,然後轉換成另一個數字字串。
我們定義字串S_{i}表示countAndSay(i),我們如果要求得S_{n},則我們需先求出S_{n-1},然後按照上述描述的方法生成,即從左到右依序掃描字串S_{n-1}中連續相同的字元的最大數目,然後將字元的統計數目轉換為數字字串再連接上對應的字元。
class Solution { public String countAndSay(int n) { String str = "1"; for (int i = 2; i <= n; ++i) { StringBuilder sb = new StringBuilder(); int start = 0; int pos = 0; while (pos < str.length()) { while (pos < str.length() && str.charAt(pos) == str.charAt(start)) { pos++; } sb.append(Integer.toString(pos - start)).append(str.charAt(start)); start = pos; } str = sb.toString(); } return str; } }
N 為給定的正整數,M 為產生的字串中的最大長度
時間複雜度:O(N * M)
空間複雜度:O(M)
具體的方法分析已經在上文中表述
由於每次得到的資料都是來自於上一次的結果,所以我們可以假設得到了上次的結果,繼而往後運算。這就運用到了遞迴。
func countAndSay(n int) string { if n == 1 { return "1" } s := countAndSay(n - 1) i, res := 0, "" length := len(s) for j := 0; j < length; j++ { if s[j] != s[i] { res += strconv.Itoa(j-i) + string(s[i]) i = j } } res += strconv.Itoa(length-i) + string(s[i]) return res }
N 為給定的正整數,M 為產生的字串中的最大長度
時間複雜度:O(N * M)
空間複雜度:O(M)
以上是Go Java演算法之外觀數列如何實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!