38. 外观数列『简单』

题目来源于力扣(LeetCode

一、题目

38. 外观数列

题目相关标签:字符串

注意:

整数序列中的每一项将表示为一个字符串。

二、解题思路

2.1 递归 + StringBuilder 方式

  1. 采用递归方式,结束条件为 n == 1 时,返回字符串 1

  2. 递归调用后,每次都得到前一项的外观数列结果

  3. 对外观数列结果进行统计

  4. 循环外观数列的字符数组

  5. 遍历出现不同值时,对前一个记录的元素 append 到 StringBuilder 中

  6. 先添加记录前一个元素出现数量的 count,再记录前一个元素的字符

  7. 需要处理遍历到最后一个元素时的情况:可能是与之前元素相同的元素,可能是与之前元素不同的元素两种情况

2.2 线性扫描 + StringBuilder 方式

  1. 定义变量记录下第一项的外观数列为 "1"

  2. 循环操作,索引从 2 到 n

  3. 每次循环都得到索引值的外观数列,从对前一索引值的外观数列进行统计和赋值得到当前索引值的外观数列

  4. 每次循环得到的外观数列都将作为下一索引值的统计和操作的对象

三、代码实现

3.1 递归 + StringBuilder 方式

public static String countAndSay(int n) {
    // 结束递归的条件
    if (n == 1) {
        return "1";
    }
    // 递归获取 n - 1 项时的外观数列
    String result = countAndSay(n - 1);

    StringBuilder sb = new StringBuilder();

    int count = 0;
    // 字符串转换成数组操作
    char[] arr = result.toCharArray();
    // 遍历前一项的外观数列字符数组
    for (int i = 0; i < arr.length; i++) {
        // 元素数量每次加 1
        count ++;
        // 与前一个元素不相同时
        if (i > 0 && arr[i] != arr[i - 1]) {
            // 先 append 数量
            sb.append(count - 1);
            // 再 append 数字
            sb.append(arr[i - 1]);
            // 数量重置为 1
            count = 1;
        }
        // 最后一个元素时的情况处理
        if (i == arr.length - 1 && count > 0) {
            // 先 append 数量
            sb.append(count);
            // 再 append 数字
            sb.append(arr[i]);
        }
    }

    return sb.toString();
}

3.2 线性扫描 + StringBuilder 方式

public static String countAndSay(int n) {
    // 根据题意,令起始项为 1
    String str = "1";
    // 依次遍历 2 ~ n
    for (int i = 2; i <= n; i++) {
        StringBuilder sb = new StringBuilder();
        char[] arr = str.toCharArray();
        // 初始数量为 1 而不是 0
        int count = 1;
        // 令 prev 初始值为数组第一位
        char prev = arr[0];
        for (int j = 1; j < arr.length; j++) {
            if (arr[j] == prev) {
                // 当前遍历元素与 prev 相同时,数量加 1
                count++;
            } else {
                // append 当前遍历元素之前的 prev 元素个数与数值
                sb.append(count).append(prev);
                // 记录下当前元素的个数,并使 prev 字符为当前元素
                count = 1;
                prev = arr[j];
            }
        }
        // append 最后遍历的元素个数与数值
        sb.append(count).append(prev);
        // 对 str 重新赋值为计算后的新字符串,即新的一项的外观数列,作为下一个遍历元素的外观数列
        str = sb.toString();
    }
    return str;
}

四、执行用时

4.1 递归 + StringBuilder 方式

4.2 线性扫描 + StringBuilder 方式

五、部分测试用例

public static void main(String[] args) {
    int num = 1;  // output:"1"
//    int num = 2;  // output:"11"   前一项为:1,则输出 1 个 1,字符串形式:11
//    int num = 3;  // output:"21"   前一项为:11,则输出 2 个 1,字符串形式:21
//    int num = 4;  // output:"1211"   前一项为:21,则输出 1 个 2,1 个 1,字符串形式:1211
//    int num = 5;  // output:"111221"   前一项为:1211,则输出 1 个 1,1 个 2,2 个 1,字符串形式:111221
//    int num = 6;  // output:"312211"   前一项为:111221,则输出 3 个 1,2 个 2,1 个 1,字符串形式:312211
    String result = countAndSay(num);
    System.out.println(result);
}
posted @ 2020-05-19 23:07  知音12138  阅读(295)  评论(0编辑  收藏  举报