Java輕鬆搞定leetcode前100系列之38. 外觀數列
題目描述:
給定一個正整數 n ,輸出外觀數列的第 n 項。
「外觀數列」是一個整數序列,從數字 1 開始,序列中的每一項都是對前一項的描述。
你可以將其視作是由遞迴公式定義的數字字串序列:
countAndSay(1) = "1"
countAndSay(n) 是對 countAndSay(n-1) 的描述,然後轉換成另一個數字字串。
前五項如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
第一項是數字 1
描述前一項,這個數是 1 即 “ 一 個 1 ”,記作 "11"
描述前一項,這個數是 11 即 “ 二 個 1 ” ,記作 "21"
描述前一項,這個數是 21 即 “ 一 個 2 + 一 個 1 ” ,記作 "1211"
描述前一項,這個數是 1211 即 “ 一 個 1 + 一 個 2 + 二 個 1 ” ,記作 "111221"
要 描述 一個數字字串,首先要將字串分割為 最小 數量的組,每個組都由連續的最多 相同字元 組成。然後對於每個組,先描述字元的數量,然後描述字元,形成一個描述組。要將描述轉換為數字字串,先將每組中的字元數量用數字替換,再將所有描述組連線起來。
例如,數字字串 "3322251" 的描述如下圖:
示例 1:
輸入:n = 1
輸出:"1"
解釋:這是一個基本樣例。
示例 2:
輸入:n = 4
輸出:"1211"
解釋:
countAndSay(1) = "1"
countAndSay(2) = 讀 "1" = 一 個 1 = "11"
countAndSay(3) = 讀 "11" = 二 個 1 = "21"
countAndSay(4) = 讀 "21" = 一 個 2 + 一 個 1 = "12" + "11" = "1211"
提示:
1 <= n <= 30
題目解答:
思路:雙指標
在這道題中,題目給定一個正整數 n(1<=n<=30),要求輸出外觀數列第 n 項。
【外觀數列】:是一個整數序列,數字由 1 開始,序列中每一項都是對前一項的描述。
例如:
1. 1
2. 11
這裡例子給出兩項,其中:
第一項由 1 開始;
第二項是對第一項的描述,這裡第一項的 1,被描述為 1 個 1,記為 11。
序列後續以此類推,都是後面對前面項的描述。其中整數序列的每一項都以字串的形式表示。
這裡,我們可以發現,除第一項外,每一項都是對前面項的描述。也就是說,只要知道前面項,那麼就能有辦法求得當前項。
現在,假設題目給定正整數 n,要求外觀數列的第 n 項。那麼這裡需要得知第 n-1 項的內容,而第 n-1 項則須知第 n-2 項,...,以此類推。而在這道題中,第一項就是 1,那麼就可以由此逐項往下遞推。
這裡主要的問題是如何去描述前一項得到當前項?
看題目中的示例,例如第 5 項,111221。現在要描述此項獲得第 6 項,現在我們直觀來看,有 3 個 1,2 個 2,1 個 1,那麼記為 312211。這就是最直觀能夠得出的結論,那我們來看看,就這個例子具體的思路:
從左往右觀察第 5 項,111221,其中 1112 這部分中,在遇到 2 之前,前面的 1 出現了 3 次,那麼此時記下出現的次數以及具體的元素,進而將其拼接。也就是 31;
同樣的,緊接部分 221,這裡,在遇到後面的 1 之前,前面的 2 出現了 2 次,這裡拼接,記為 22;
最後部分的 1,後續沒有相同的元素,也就僅出現一次,記為 11。
根據上面的思路,當給定任意的正整數 n(1<=n<=30)時,我們可以通過下面雙指標的做法,去逐項描述,求得第 n 項:
首先定義變數 pre 記錄前一項,初始化為空字串;定義變數 cur 記錄當前項,初始化為 '1'(第一項為 1);
定義雙指標 start, end 均指向序列項的頭部,這裡用於統計元素出現的次數;
由於給定的n≥1,這裡由第 2 項開始逐項對前一項進行描述(注意,要將 cur 賦值給 pre,並初始化 cur 為空字串,重新拼接得到當前項):
從左往右遍歷 pre,當元素相同時,移動 end 指標,直至元素不相同時,那麼此時 end-start 就是相同元素的個數,而 start 指標指向的元素就是重複的元素,進行拼接,cur += str(end-start)+pre[start]。
此時要讓 start 指向 end 所在的位置,開始記錄下個元素出現的次數;
重複上面的步驟,直至 end 指標到達序列項尾部,便可得到當前項。
逐項對前面一項描述開始時,都應該重置 start、end 指標指向序列項頭部,同時應將 cur 賦值給 pre,初始化 cur,也就是前面注意部分所說的內容(可結合程式碼理解)。然後,再次重複第三個步驟。
程式碼如下:
public String countAndSay(int n) {
StringBuilder pre = new StringBuilder("1");
StringBuilder cur = new StringBuilder("1");
for (int i = 1; i < n; i++) {
pre = cur;
cur = new StringBuilder();
int start=0,end=0;
while (end<pre.length()){
while (end<pre.length()&&pre.charAt(start)==pre.charAt(end)){
end++;
}
cur=cur.append(end-start).append(pre.charAt(start));
start=end;
}
}
return cur.toString();
}
相關文章
- LeetCode-038-外觀數列LeetCode
- 辦公室革命,教你輕鬆搞定輕鬆玩轉ExcelExcel
- 帶你十天輕鬆搞定 Go 微服務系列(五)Go微服務
- 帶你十天輕鬆搞定 Go 微服務系列(六)Go微服務
- 帶你十天輕鬆搞定 Go 微服務系列(七)Go微服務
- 帶你十天輕鬆搞定 Go 微服務系列(一)Go微服務
- 帶你十天輕鬆搞定 Go 微服務系列(二)Go微服務
- 帶你十天輕鬆搞定 Go 微服務系列(三)Go微服務
- 帶你十天輕鬆搞定 Go 微服務系列(四)Go微服務
- 【Java多執行緒】輕鬆搞定Java多執行緒(二)Java執行緒
- Apache Storm系列 之二( 輕鬆搞定 Storm 安裝與啟動)ApacheORM
- 100行程式碼,輕鬆搞定文字編輯器中草稿箱行程
- 輕鬆搞定專案流程自動化
- 3D 穿梭效果?使用 CSS 輕鬆搞定3DCSS
- Android輕鬆搞定Dialog提示動畫效果Android動畫
- 12步輕鬆搞定python裝飾器Python
- 帶你十天輕鬆搞定 Go 微服務系列(八、服務監控)Go微服務
- 帶你十天輕鬆搞定 Go 微服務系列(九、鏈路追蹤)Go微服務
- 學習筆記:帶你十天輕鬆搞定 Go 微服務系列(一)筆記Go微服務
- 學習筆記:帶你十天輕鬆搞定 Go 微服務系列(二)筆記Go微服務
- Java:如何輕鬆獲取當前執行的方法名Java
- 填報指令碼之輕鬆搞定複雜表的資料入庫指令碼
- 輕鬆搞定專案管理軟體、分配任務專案管理
- 一份配置,輕鬆搞定Vue表單渲染Vue
- 上億條資料,OurwayBI也能輕鬆搞定
- MySQL8.0輕鬆搞定GTID組複製MySql
- Jenkins部署安裝,輕鬆三步搞定Jenkins
- 輕鬆搞定實時分析及監控大屏
- 輕鬆搞定面試中的連結串列題目面試
- 輕鬆搞定Windows惡意程式碼攻擊(轉)Windows
- 一文輕鬆搞定 tarjan 演算法(二)演算法
- 軟體設計模式系列之十二——外觀模式設計模式
- 軟體測試之30分鐘輕鬆搞定正規表示式基礎
- 輕鬆搞定分組報表中的各種排序排序
- MySQL8.0輕鬆搞定GTID主從複製MySql
- MySQL8.0輕鬆搞定GTID主主複製MySql
- 輕鬆搞定面試中的二叉樹題目面試二叉樹
- 六大絕招輕鬆搞定系統更新(轉)