题目
类型:双指针
解题思路
如果一块原本竖立的骨牌最终倒下,必然是「受到来自左侧向右的力」或者「受到来自右侧向左的力」。
基于此,可以创建两个二维数组 l 和 r 分别存储每个位置 i 的左侧和右侧的受力情况,每个的 l[i] 和 r[i] 分别存储「左侧」和「右侧」的最近受力点下标,以及该力的方向。
然后枚举所有 dominoes[i] 为 . 的位置,获取其左侧的最近受力点 loc1 和受力方向 dire1,以及其右侧的最近受力点 loc2 和受力方向 dire2,并进行分情况讨论即可。
根据左右侧受力情况修改骨牌状态可通过「双指针」实现。
代码
class Solution {
static int N = 100010;
static int[][] l = new int[N][2], r = new int[N][2];
public String pushDominoes(String dominoes) {
char[] cs = dominoes.toCharArray();
int n = cs.length;
for (int i = 0, j = -1; i < n; i++) {
if (cs[i] != '.') j = i;
l[i] = new int[]{j, j != -1 ? cs[j] : '.'};
}
for (int i = n - 1, j = -1; i >= 0; i--) {
if (cs[i] != '.') j = i;
r[i] = new int[]{j, j != -1 ? cs[j] : '.'};
}
for (int i = 0; i < n; ) {
if (cs[i] != '.' && ++i >= 0) continue;
int j = i;
while (j < n && cs[j] == '.') j++;
j--;
int[] a = l[i], b = r[j];
int loc1 = a[0], dire1 = a[1], loc2 = b[0], dire2 = b[1];
if (loc1 == -1 && loc2 == -1) { // 两侧无力
} else if (loc1 == -1) { // 只有右侧有力,且力的方向向左
if (dire2 == 'L') update(cs, i, j, 'L', 'L');
} else if (loc2 == -1) { // 只有左侧有力,且力的方向向右
if (dire1 == 'R') update(cs, i, j, 'R', 'R');
} else { // 两侧有力,且两力方向「不同时」反向
if (!(dire1 == 'L' && dire2 == 'R')) update(cs, i, j, (char)dire1, (char)dire2);
}
i = j + 1;
}
return String.valueOf(cs);
}
void update(char[] cs, int l, int r, char c1, char c2) {
for (int p = l, q = r; p <= q; p++, q--) {
if (p == q && c1 != c2) continue;
cs[p] = c1; cs[q] = c2;
}
}
}