问题描述
小S玩起了多米诺骨牌,他排列了一行骨牌,并可能将某些骨牌向左或向右推倒。随着骨牌连锁反应的进行,一些骨牌可能因为左右两侧受力平衡而保持竖立。现在小S想要知道在所有动作完成后,哪些骨牌保持竖立。
给定一个表示骨牌初始状态的字符串,其中:
- "L" 表示该位置的骨牌将向左倒。
- "R" 表示该位置的骨牌将向右倒。
- "." 表示该位置的骨牌初始时保持竖立。
模拟整个骨牌倒下的过程,求出最终仍然保持竖立的骨牌的数目和位置。
测试样例
样例1:
输入:
num = 14,data = ".L.R...LR..L.."输出:'4:3,6,13,14'
样例2:
输入:
num = 5,data = "R...."输出:'0'
样例3:
输入:
num = 1,data = "."输出:'1:1'
解题思路
1. 数据结构准备
- 定义了两个整型数组
t和t1,长度都为num(骨牌的总数)。这两个数组将用于记录在从左到右和从右到左模拟骨牌倒下过程中,每个位置骨牌受到的影响情况。 - 使用
StringBuffer类型的sb来存储输入的表示骨牌初始状态的字符串,方便后续对字符串中的字符进行修改和操作。
2. 从左到右模拟骨牌倒下(向右传递影响)
-
通过一个循环从索引
1到num - 1遍历骨牌状态字符串(因为第一个骨牌左侧没有骨牌影响它,所以从第二个开始考虑)。 -
在每次循环中,检查当前骨牌(索引为
i)及其前一个骨牌(索引为i - 1)的状态:- 如果前一个骨牌是向右倒(
sb.charAt(i - 1) == 'R')且当前骨牌是竖立(sb.charAt(i) == '.'),或者前一个骨牌已经受到向右的影响(t[i - 1] > 0)且当前骨牌是竖立,那么当前骨牌会受到向右的影响,将t[i]设置为t[i - 1] + 1,表示当前骨牌受到向右的力的传递影响程度增加了1。
- 如果前一个骨牌是向右倒(
3. 从右到左模拟骨牌倒下(向左传递影响)
-
接着通过另一个循环从索引
num - 2到0反向遍历骨牌状态字符串(因为最后一个骨牌右侧没有骨牌影响它,所以从倒数第二个开始考虑)。 -
在每次循环中,检查当前骨牌(索引为
i)及其后一个骨牌(索引为i + 1)的状态:- 如果后一个骨牌是向左倒(
sb.charAt(i + 1) == 'L')且当前骨牌是竖立(sb.charAt(i) == '.'),或者后一个骨牌已经受到向左的影响(t1[i + 1] < 0)且当前骨牌是竖立,那么当前骨牌会受到向左的影响,将t1[i]设置为t1[i + 1] - 1,表示当前骨牌受到向左的力的传递影响程度增加了(这里是减少,因为是向左的力,用负数表示)1。
- 如果后一个骨牌是向左倒(
4. 确定最终保持竖立的骨牌
-
创建两个新的
StringBuffer类型的变量s1和s2,以及一个整型变量sum。s1将用于存储最终保持竖立的骨牌的位置,sum用于统计保持竖立的骨牌的数目,s2将用于构建最终要返回的结果字符串。 -
通过一个循环从索引
0到num - 1再次遍历骨牌状态字符串。 -
对于每个位置的骨牌,如果它初始状态是竖立(
sb.charAt(i) == '.')并且它受到的向左和向右的影响总和为0(t[i] + t1[i] == 0),说明这个骨牌在整个倒下过程中左右受力平衡,仍然保持竖立。此时:- 将该骨牌的位置(索引
i + 1,因为题目可能要求从1开始计数位置)添加到s1中,并在后面添加逗号作为分隔符。 - 将
sum的值增加1,表示找到一个保持竖立的骨牌。
- 将该骨牌的位置(索引
5. 构建并返回结果
- 将保持竖立的骨牌的数目
sum、冒号以及存储位置的字符串s1(去掉最后一个多余的逗号)依次添加到s2中。 - 最后返回
s2转换为字符串后的结果,这个结果包含了最终保持竖立的骨牌的数目以及它们的位置信息。
解题代码
import java.util.Arrays;
public class Main {
public static String solution(int num, String data) {
// Please write your code here
int i = 0;
int[] t = new int[num];
int[] t1 = new int[num];
StringBuffer sb = new StringBuffer(data);
for(i = 1; i < num; i++)
{
if((sb.charAt(i-1) == 'R' && sb.charAt(i) == '.') || (t[i-1]>0 && sb.charAt(i) == '.')){//sb.replace(i, i+1, "R");
t[i] = t[i-1] + 1;
}
}
//System.out.println(Arrays.toString(t));
for(i = num - 2; i >= 0; i--)
{
if((sb.charAt(i+1) == 'L' && sb.charAt(i) == '.') || (t1[i+1]<0 && sb.charAt(i) == '.')){//sb.replace(i, i+1, "L");
t1[i] = t1[i+1] - 1;
}
}
//System.out.println(Arrays.toString(t1));
StringBuffer s1 = new StringBuffer();
StringBuffer s2 = new StringBuffer();
int sum = 0;
for(i = 0; i < num; i++)
{
if(sb.charAt(i) == '.' && t[i]+t1[i] == 0)
{
s1.append(i+1).append(',');
sum++;
}
}
//System.out.println(Arrays.toString(t));
s2.append(sum).append(':').append(s1);
s2.deleteCharAt(s2.length()-1);
return s2.toString();
}
public static void main(String[] args) {
// You can add more test cases here
System.out.println(solution(14, ".L.R...LR..L.."));
System.out.println(solution(5, "R...."));
System.out.println(solution(1, "."));
}
}