题目:
给定一个字符串,该字符串仅包含R和L字符;初始时,每个位置都有一个机器人。机器人移动10^100次,每次的移动规则是:若其所在的位置是R,则向右移动;若其所在的位置是L,则向左移动。字符串保证最左边的字符是R,最右边的字符是L。最后输出每个位置的机器人的数量。
输入:
RRLRL
输出:
0 1 2 1 1
输入:
RRRRRLRLRL
输出:
0 0 0 0 3 3 1 1 1 1
解:
不是什么聪明的做法,代码也一大堆,描述也没描述清楚……轻喷
(仅供个人复习使用…)
大概思路是:
- 首先遍历一遍数组,根据每个位置的R和L,进行计数,count数组。
计数的标准是:(记当前位置为i,当前位置的字符为ch)(可以合并两个步骤。)
- 如果ch为R,且前一个字符也是R,则count[i] = count[i - 1] + 1;
- 如果ch为R,前一个字符是L,则count[i] = 1;(即重新计数)
- 如果ch为L,前一个字符是R,则count[i] = 1 ;
- 如果ch为L,且前一个字符也是L,则要更新之前连续的为L字符的位置,更新规则是:将当前位置前面所有连续的L位置的count+1。
这样获得最后的count数组。
- 根据count数组获得结果数组
遍历结果数组,并观察字符数组,更新res数组,更新规则是:
- 如果当前字符是R,且下一个字符也是R,则res[i] = 0;
- 如果当前字符是R,下一个字符是L,则当前是RL分界处。在10^100次移动后该位置可能累积了很多机器人。计算方式是:
- 如果count[i] 是偶数,则说明当前位置前面有奇数个R。设其前面的一个位置为idx。
- 如果idx与当前位置的距离为奇数距离,即走奇数步就可以到达当前位置。其剩余可走的步数也为奇数次。从当前位置开始,走奇数次,最后一定会落到当前位置的下一个位置。
- 如果idx与当前位置的距离是偶数举例,同理,该位置的机器人最后一定会落到当前位置。
计数方法是:res[i] += count[i] / 2,下一位置:res[i + 1] += count[i] / 2
- 如果count[i]是奇数,res[i] += count[i] / 2 + 1;下一位置:res[i + 1] += count[i] / 2
- 如果count[i] 是偶数,则说明当前位置前面有奇数个R。设其前面的一个位置为idx。
- 如果当前字符是L,且前一个字符也是L,则res[i] = 0;
- 如果当前字符是L,前一个字符是R,则同理啊。更新
- 背后的逻辑是什么:见图片
描述一大堆。下面贴代码:
private static int[] solution2(String str) {
int n = str.length();
int[] count = new int[n];
char[] array = str.toCharArray();
int i = 1;
count[0] = 1;
char pre = 'R';
while(i < n) {
char ch = array[i];
// 我这两段shit代码合在一起写好像也没问题 ——并不能
if(pre == 'R') {
if(pre == ch) {
// 如果是连续的R
count[i] = count[i - 1] + 1;
}else {
// 如果是RL的交界处
pre = 'L';
count[i] = 1;
}
}else {
if(pre == ch) {
// 如果是连续的L,更新前面L的取值
// 应该可行吧(我猜
int j = i - 1;
while(j >= 0 && array[j] == 'L') {
count[j]++;
j--;
}
count[i] = 1;
}else {
// 如果是LR交界处
pre = 'R';
count[i] = 1;
}
}
i++;
}
// 根据字符统计数组获得结果数组
i = 0;
int[] res = new int[n];// 结果数组
while(i < n) {
char ch = array[i];
if(ch == 'R' && ch == array[i + 1]) {
// 如果当前字符是R,且下一个字符也是R
res[i] = 0;
}else if(ch == 'R') {
// 如果当前字符是R,下一个字符是L,统计当前R位置的计数
if(count[i] % 2 == 0) {
// 当前位置累加起来有偶数个R
res[i] += count[i] / 2;
res[i + 1] += count[i] / 2;
}else {
res[i] += count[i] / 2 + 1;
res[i + 1] += count[i] / 2;
}
}else if(ch == 'L' && ch == array[i - 1]) {
// 如果当前字符是L,且前一个字符也是L
res[i] = 0;
}else if(ch == 'L' && array[i - 1] == 'R') {
// 如果当前字符是L,上一个字符是R,更新当前位置和前一位置的计数
if(count[i] % 2 == 0) {
res[i] += count[i] / 2;
res[i - 1] += count[i] / 2;
}else {
res[i] += count[i] / 2 + 1;
res[i - 1] += count[i] / 2;
}
}
i++;
}
return res;
}