LeetCode 外观数列

LeetCode 外观数列

题设

给定一个正整数 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” 的描述如下图:
在这里插入图片描述

示例

输入:n = 1
输出:"1"
解释:这是一个基本样例。

输入: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返回值为“1”
  • 如果n!=1,则需要进行处理,根据n-1对应的字符串找到第n个字符串,将处理过程抽象成getSequence(String s)方法,s即为第n-1个外观序列对应的字符串,也就是 countAndSay(n-1) 的返回值
  • 对我而言,搞清楚递归的过程,对于第n-1个字符串的处理相对而言就比较简单一些。我最初的想法是新建一个Node结点,记录当前的字符和其本次出现的次数,看过一些题解后发现StringBuffer更符合题目的情形。定义StringBuffer result用于存放结果,定义一个currentChar用于保存即将存入StringBuffer的字符,定义计数器count记录currentChar的出现次数。遍历过程中如果出现新字符,就把currentCharcount存入result中。注意,此时新字符已经出现一次,所以新字符的出现次数已经是1,更新currentCharcount即可
  • 循环结束时,将当时的currentCharcount存入result即可

代码如下

	public static String countAndSay(int n){
	    //递归出口
	    if(n == 1){
	        return  "1";
	    } else{
	       /*
	        如果非1,则根据当前n-1的返回值
	        通过getSequence(String)函数处理n-1的字符串得到第n个字符串
	         */
	        return getSequence(countAndSay(n-1));
	    }
	}
    public static String getSequence(String s){
      //计数器,记录当前字符重复次数
      int count = 0;
      int len = s.length();
      //记录即将被写入StringBuffer的字符
      char currentChar = s.charAt(0);
      //result记录当前字符串s的返回结果
      StringBuffer result = new StringBuffer();
      //遍历s的每个字符
      for (int i = 0; i < len; i++) {
          //如果当前的i指向的字符同currentChar相等说明当前字符重复,count加一
          if (s.charAt(i) == currentChar){
              count++;
          }else {
              //否则说明出现新字符,将旧的currentChar存入result,count修改为1
              result.append(count);
              result.append(currentChar);
              currentChar = s.charAt(i);
              count=1;
          }
      }
      //循环结束,将最后的一个currentChar存入结果
      result.append(count);
      result.append(currentChar);
      return result.toString();
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值