所謂外觀數(shù)列砸民,就是后一個(gè)數(shù)列是對前一個(gè)數(shù)列的描述贰锁。打個(gè)比方:
序列號1: 1
序列號2: 11 這是對上一個(gè)數(shù)據(jù)1的描述伦忠,上一個(gè)數(shù)據(jù)為1個(gè)1崇众,記做:11.
序列號3: 21 這是對上一個(gè)數(shù)據(jù)11的描述掂僵,上一個(gè)數(shù)據(jù)為2個(gè)1航厚,記做:21.
序列號4: 1211 這是對上一個(gè)數(shù)據(jù)21的描述,上一個(gè)數(shù)據(jù)為1個(gè)2锰蓬,1個(gè)1幔睬,記做:1211.
...
題目是,給出相應(yīng)的序列號芹扭,算出對應(yīng)的外觀數(shù)列麻顶。
要找序列號為n
的外觀數(shù)列,那么就得知道序列號為n-1
的外觀數(shù)列的值舱卡,要想知道序列號為n-1
的外觀數(shù)列的值辅肾,就得知道序列號為n-2
的外觀數(shù)列的值...
以此類推,很容易聯(lián)想到用遞歸轮锥,而遞歸的終止條件可以是以下兩個(gè):
if (n == 1) return "1";
if (n == 2) return "11";
這樣做就能保證preString
的長度至少大于等于2矫钓,不用做額外的判斷。preString
代表上一個(gè)外觀數(shù)列的值交胚,在下面的代碼中會提到份汗。
然后,兩指針最初分別指向外觀數(shù)列中第0位和第1位蝴簇,當(dāng)指向的元素相同時(shí)杯活,right
指針向前移動一位,否則添加對應(yīng)元素熬词。
left
和right
指針的差值就是某個(gè)數(shù)字的出現(xiàn)的次數(shù)旁钧。
// 遞歸算法
private String getStringByCount(int n) {
if (n == 1) return "1";
if (n == 2) return "11";
// 遞歸計(jì)算前一個(gè)元素的值
char[] preString = getStringByCount(n - 1).toCharArray();
int left = 0;
StringBuilder result = new StringBuilder();
for (int right = 1; right < preString.length; ) {
// 不同位上的元素不一樣
if (preString[left] != preString[right]) {
// 開始構(gòu)建描述數(shù)列,此時(shí)right - left代表著中間隔了多少個(gè)相同的元素
result.append((right - left)).append(preString[left]);
left = right;
}
// 每個(gè)遍歷互拾,right右移一位
right++;
// 當(dāng)達(dá)到元素的末尾時(shí)
if (right == preString.length) {
result.append((right - left)).append(preString[left]);
}
}
return result.toString();
}