public int magicalString(int n) {
// 122
// 如果预测的n位小于4,则直接返回1
if(n<4){
return 1;
}
// 如果大于4,则递推求解
// 初始化结果变量为 1
int res = 1;
// 初始化缓存数组
int[] cache = new int[n];
// 前三位为122
cache[0] = 1;
cache[1] = 2;
cache[2] = 2;
// 定义数字 下标为3 122
int numIndex = 3;
// 定义个数下标为2 122
int countIndex = 2;
// 当 数字下标还小于n时继续递推查找
while(numIndex < n) {
// 获取个数下标数字
int count = cache[countIndex];
int curNum = 3 - cache[numIndex-1];
// 如果为1,代表要生成和数字下标左边 1个 不同的数
// 填充进数组, 数字下标右移
cache[numIndex++] = curNum;
if(curNum==1){
res++;
}
count--;
// 如果为2,则代表要生成和数字下标左边 2 个不同的数
if(count>0 && numIndex < n){
// 填充进数组, 数字下标右移
cache[numIndex++] = curNum;
if(curNum==1){
res++;
}
}
// 个数下标继续右移
countIndex++;
}
// 返回结果
return res;
}
这里的关键是数字序列 会比 个数序列会多,所以我们可以通过这个间隔差来通过双指针解决递推神奇字符串的功能
举个例子,首先我们可以确定的神奇字符串前三个数字为 122,
此时 个数序列其实只为 12 而已,
而此时也能确定的是 个数序列 将会是 122, 也就是说数字数字序列接下来将会有两个相同的数字出现,而此时 2已经出现了两次,那么就只能是两个1了,那么通过个数序列 122,我们推倒出
数字序列将会是 12211,此时,我们又可以预知到个数序列将会是 12211,那么数字序列接下来将是一个连续的数字,而此时最后一个数字已经是1了,那么只能是 122112,根据个数序列,接下来还是一个连续的相同数字,那么只能是 1221121,根据这个数字序列,我们 又可以预知到接下来将是两个连续的相同数组,那么只能是 122112122,以此类推.