问题描述:
神奇字符串 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 的数目。
样例如下:
代码及思路如下(采用双指针):
public class MagicalString {
// 神奇字符串 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 的数目。
public static int magicalString(int n) {//双指针解决
if (n<=3) return 1;
int count = 0;//记录1的个数
int[] a = new int[n];
a[0] = 1;//初始化
a[1] = 2;
a[2] = 2;
int st = 2;
int end = 3;//指向当前的位置
while (end<=n-1){
int temp = a[st];//记录要加的次数
int add;//找出要加的数
if (a[end-1]==1) add = 2;
else add = 1;
int i = 0;
boolean flag = false; //用于判断是否为正常退出
for (; i <=temp-1; i++) {
a[end+i] = add;
if (end+i>=n-1) {
flag = true;
break;
}
}
if (flag) end++; //若为break,则需要end++
end = end+i;//指针指向未添加数据的位置
st++;//开始指针移动
}
for (int i = 0; i < n; i++) {
if (a[i]==1) count++;
}
return count;
}
public static void main(String[] args) {
System.out.println(magicalString(1));
}
}
结果入下: