算法日志 --- 11.21---神奇字符串

110 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

恐怖周一,要马上开启周会 + 需求了

神奇字符串

该题出自力扣的481题 —— 神奇字符串【中等题】

审题

神奇字符串 s 仅由 '1' 和 '2' 组成,并需要遵守下面的规则: 神奇字符串 s 的神奇之处在于,串联字符串中 '1' 和 '2' 的连续出现次数可以生成该字符串。 s 的前几个元素是 s = "1221121221221121122……" 。如果将 s 中连续的若干 1 和 2 进行分组,可以得到 "1 22 11 2 1 22 1 22 11 2 11 22 ......" 。每组中 1 或者 2 的出现次数分别是 "1 2 2 1 1 2 1 2 2 1 2 2 ......" 。上面的出现次数正是 s 自身。 给你一个整数 n ,返回在神奇字符串 s 的前 n 个数字中 1 的数目。

  • 这道题初看真的好拗口,而且对比了题意和测试用例,也不是很好理解。简单概括就是,整个字符串只有12,两种字符,而且字符之间必定交互出现,决定出现的数字个数与前一个数相关
  • 数字出现的频率与前一个数相关,但是决定用哪个数字就是当前数字的前一个的逆反,例如:1则是2,2则是1
  • 因此思路出来了,利用前三个数字去推导,也就是模拟题型
    • 判断如果长度小于4,则直接剪枝
    • 开辟一个char型数组,长度 n + 10,防止溢出
    • 利用循环,不断推导
      • 只要知道需要填充的数字
      • 知道需要填充的个数
      • 还原数组即可
    • 最终返回即可

编码

class Solution {
    public int magicalString(int n) {
        if (n<4)return 1;
        int sum = 1;
        int[] chars = new int[n + 10];
        chars[0] = 1;
        chars[1] = 2;
        chars[2] = 2;
        int i = 3;
        int q = chars[2];
        for (int j = 2; j < n && i<n;j++) {
            // 个数
            int aChar = chars[j];
            // 填充的数
            q = (q ^ 3);

            for (int k = 0; k < aChar && i + k<=n; k++) {
                chars[i++] = q;
                if (q == 1)sum++;
            }
        }
        return sum;
    }
}

image.png