838. 推多米诺
n 张多米诺骨牌排成一行,将每张多米诺骨牌垂直竖立。在开始时,同时把一些多米诺骨牌向左或向右推。
每过一秒,倒向左边的多米诺骨牌会推动其左侧相邻的多米诺骨牌。同样地,倒向右边的多米诺骨牌也会推动竖立在其右侧的相邻多米诺骨牌。
如果一张垂直竖立的多米诺骨牌的两侧同时有多米诺骨牌倒下时,由于受力平衡, 该骨牌仍然保持不变。
就这个问题而言,我们会认为一张正在倒下的多米诺骨牌不会对其它正在倒下或已经倒下的多米诺骨牌施加额外的力。
给你一个字符串 dominoes 表示这一行多米诺骨牌的初始状态,其中:
dominoes[i] = ‘L’,表示第 i 张多米诺骨牌被推向左侧,
dominoes[i] = ‘R’,表示第 i 张多米诺骨牌被推向右侧,
dominoes[i] = ‘.’,表示没有推动第 i 张多米诺骨牌。
返回表示最终状态的字符串。
害 想用双指针遍历 然后想半天也没写出来hhh
参考评论区一大佬的想法:
1、LL之间的全L;
2、RR之间的全R;
3、LR不变,RL中间靠;
4、最左边默认有个L,最右边默认有个R,这样方便处理
这思路瞬间清晰许多
public static String pushDominoes(String dominoes) {
//1、LL之间的全L;2、RR之间的全R;3、LR不变,RL中间靠;5、最左边默认有个L,最右边默认有个R,这样方便处理
dominoes = new StringBuilder("L").append(dominoes).append("R").toString();
StringBuilder ans = new StringBuilder();
//初始化左右指针
int leftIndex = 0, rightIndex = 1;
while (rightIndex < dominoes.length()) {
while (rightIndex < dominoes.length() && dominoes.charAt(rightIndex) == '.') {
rightIndex++;
}
char leftChar = dominoes.charAt(leftIndex);
char rightChar = dominoes.charAt(rightIndex);
if (leftChar == rightChar) {
for (int i = leftIndex+1 ; i < rightIndex; i++) {
ans.append(leftChar);
}
} else if (leftChar == 'R' && rightChar == 'L') {
// 这里as计算两者之间有多少个 .
int as = rightIndex - leftIndex - 1;
for (int i = 0; i < as / 2 ; i++) {
ans.append('R');
}
// 如果当前'.'的个数为奇数的话 我们还需要为其添加一个中间的竖直骨牌 即R...L -> RR.LL
if (as % 2 == 1) {
ans.append('.');
}
for (int i = 0; i < as / 2; i++) {
ans.append('L');
}
} else if(leftChar == 'L'&& rightChar == 'R'){
for (int i = leftIndex + 1; i < rightIndex; i++) {
ans.append('.');
}
}
//把此次rightIndex指向的char添加到ans中
ans.append(rightChar);
//更新左右指针的位置,使其向下一对LR/RL/LL/RR 移动
leftIndex = rightIndex;
rightIndex++;
}
//去掉在最右侧加入的 R
return ans.substring(0,ans.length() - 1).toString();
}
看到评论区好多大佬都是用位运算符的,然而我好像都没用过…恶补一下
注
操作符 | 解(算术左移和算术右移主要用来进行有符号数的倍增、减半) |
---|---|
number << i | 相当于 number * 2i ,算数左移AKA逻辑左移,高位溢出,低位补0 |
number >> i | 相当于 number / 2i ,算数右移,低位溢出,高位补0 |
number >>> i | 表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0 |
例
图源