diff --git a/solution/0800-0899/0838.Push Dominoes/README.md b/solution/0800-0899/0838.Push Dominoes/README.md
index e6f79c7abba0b..f9155dcaa5a0c 100644
--- a/solution/0800-0899/0838.Push Dominoes/README.md
+++ b/solution/0800-0899/0838.Push Dominoes/README.md
@@ -29,9 +29,9 @@ tags:
给你一个字符串 dominoes
表示这一行多米诺骨牌的初始状态,其中:
- dominoes[i] = 'L'
,表示第 i
张多米诺骨牌被推向左侧,
- dominoes[i] = 'R'
,表示第 i
张多米诺骨牌被推向右侧,
- dominoes[i] = '.'
,表示没有推动第 i
张多米诺骨牌。
+ dominoes[i] = 'L'
,表示第 i
张多米诺骨牌被推向左侧,
+ dominoes[i] = 'R'
,表示第 i
张多米诺骨牌被推向右侧,
+ dominoes[i] = '.'
,表示没有推动第 i
张多米诺骨牌。
返回表示最终状态的字符串。
@@ -57,9 +57,9 @@ tags:
提示:
- n == dominoes.length
- 1 <= n <= 105
- dominoes[i]
为 'L'
、'R'
或 '.'
+ n == dominoes.length
+ 1 <= n <= 105
+ dominoes[i]
为 'L'
、'R'
或 '.'
@@ -68,7 +68,30 @@ tags:
-### 方法一
+### 方法一:多源 BFS
+
+把所有初始受到推力的骨牌(`L` 或 `R`)视作 **源点**,它们会同时向外扩散各自的力。用队列按时间层级(0, 1, 2 …)进行 BFS:
+
+我们定义 $\text{time[i]}$ 记录第 *i* 张骨牌第一次受力的时刻,`-1` 表示尚未受力,定义 $\text{force[i]}$ 是一个长度可变的列表,存放该骨牌在同一时刻收到的方向(`'L'`、`'R'`)。初始时把所有 `L/R` 的下标压入队列,并将它们的时间置 0。
+
+当弹出下标 *i* 时,若 $\text{force[i]}$ 只有一个方向,骨牌就会倒向该方向 $f$。设下一张骨牌下标为
+
+$$
+j =
+\begin{cases}
+i - 1, & f = L,\\
+i + 1, & f = R.
+\end{cases}
+$$
+
+若 $0 \leq j < n$:
+
+- 若 $\text{time[j]}=-1$,说明 *j* 从未受力,记录 $\text{time[j]}=\text{time[i]}+1$ 并入队,同时把 $f$ 写入 $\text{force[j]}$。
+- 若 $\text{time[j]}=\text{time[i]}+1$,说明它在同一“下一刻”已受过另一股力,此时只把 $f$ 追加到 $\text{force[j]}$,形成对冲;后续因 `len(force[j])==2`,它将保持竖直。
+
+队列清空后,所有 $\text{force[i]}$ 长度为 1 的位置倒向对应方向;长度为 2 的位置保持 `.`。最终将字符数组拼接为答案。
+
+时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是骨牌的数量。
@@ -242,44 +265,40 @@ func pushDominoes(dominoes string) string {
```ts
function pushDominoes(dominoes: string): string {
const n = dominoes.length;
- const map = {
- L: -1,
- R: 1,
- '.': 0,
- };
- let ans = new Array(n).fill(0);
- let visited = new Array(n).fill(0);
- let queue = [];
- let depth = 1;
+ const q: number[] = [];
+ const time: number[] = Array(n).fill(-1);
+ const force: string[][] = Array.from({ length: n }, () => []);
+
for (let i = 0; i < n; i++) {
- let cur = map[dominoes.charAt(i)];
- if (cur) {
- queue.push(i);
- visited[i] = depth;
- ans[i] = cur;
+ const f = dominoes[i];
+ if (f !== '.') {
+ q.push(i);
+ time[i] = 0;
+ force[i].push(f);
}
}
- while (queue.length) {
- depth++;
- let nextLevel = [];
- for (let i of queue) {
- const dx = ans[i];
- let x = i + dx;
- if (x >= 0 && x < n && [0, depth].includes(visited[x])) {
- ans[x] += dx;
- visited[x] = depth;
- nextLevel.push(x);
+
+ const ans: string[] = Array(n).fill('.');
+ let head = 0;
+ while (head < q.length) {
+ const i = q[head++];
+ if (force[i].length === 1) {
+ const f = force[i][0];
+ ans[i] = f;
+ const j = f === 'L' ? i - 1 : i + 1;
+ if (j >= 0 && j < n) {
+ const t = time[i];
+ if (time[j] === -1) {
+ q.push(j);
+ time[j] = t + 1;
+ force[j].push(f);
+ } else if (time[j] === t + 1) {
+ force[j].push(f);
+ }
}
}
- queue = nextLevel;
}
- return ans
- .map(d => {
- if (!d) return '.';
- else if (d < 0) return 'L';
- else return 'R';
- })
- .join('');
+ return ans.join('');
}
```
diff --git a/solution/0800-0899/0838.Push Dominoes/README_EN.md b/solution/0800-0899/0838.Push Dominoes/README_EN.md
index ce232677d18a7..d41fed93a68d5 100644
--- a/solution/0800-0899/0838.Push Dominoes/README_EN.md
+++ b/solution/0800-0899/0838.Push Dominoes/README_EN.md
@@ -29,9 +29,9 @@ tags:
You are given a string dominoes
representing the initial state where:
- dominoes[i] = 'L'
, if the ith
domino has been pushed to the left,
- dominoes[i] = 'R'
, if the ith
domino has been pushed to the right, and
- dominoes[i] = '.'
, if the ith
domino has not been pushed.
+ dominoes[i] = 'L'
, if the ith
domino has been pushed to the left,
+ dominoes[i] = 'R'
, if the ith
domino has been pushed to the right, and
+ dominoes[i] = '.'
, if the ith
domino has not been pushed.
Return a string representing the final state.
@@ -56,9 +56,9 @@ tags:
Constraints:
- n == dominoes.length
- 1 <= n <= 105
- dominoes[i]
is either 'L'
, 'R'
, or '.'
.
+ n == dominoes.length
+ 1 <= n <= 105
+ dominoes[i]
is either 'L'
, 'R'
, or '.'
.
@@ -67,7 +67,30 @@ tags:
-### Solution 1
+### Solution 1: Multi-Source BFS
+
+Treat all initially pushed dominoes (`L` or `R`) as **sources**, which simultaneously propagate their forces outward. Use a queue to perform BFS layer by layer (0, 1, 2, ...):
+
+We define $\text{time[i]}$ to record the first moment when the _i_-th domino is affected by a force, with `-1` indicating it has not been affected yet. We also define $\text{force[i]}$ as a variable-length list that stores the directions (`'L'`, `'R'`) of forces acting on the domino at the same moment. Initially, push all indices of `L/R` dominoes into the queue and set their `time` to 0.
+
+When dequeuing index _i_, if $\text{force[i]}$ contains only one direction, the domino will fall in that direction $f$. Let the index of the next domino be:
+
+$$
+j =
+\begin{cases}
+i - 1, & f = L,\\
+i + 1, & f = R.
+\end{cases}
+$$
+
+If $0 \leq j < n$:
+
+- If $\text{time[j]} = -1$, it means _j_ has not been affected yet. Record $\text{time[j]} = \text{time[i]} + 1$, enqueue it, and append $f$ to $\text{force[j]}$.
+- If $\text{time[j]} = \text{time[i]} + 1$, it means _j_ has already been affected by another force at the same "next moment." In this case, append $f$ to $\text{force[j]}$, causing a standoff. Subsequently, since $\text{len(force[j])} = 2$, it will remain upright.
+
+After the queue is emptied, all positions where $\text{force[i]}$ has a length of 1 will fall in the corresponding direction, while positions with a length of 2 will remain as `.`. Finally, concatenate the character array to form the answer.
+
+The complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the number of dominoes.
@@ -241,44 +264,40 @@ func pushDominoes(dominoes string) string {
```ts
function pushDominoes(dominoes: string): string {
const n = dominoes.length;
- const map = {
- L: -1,
- R: 1,
- '.': 0,
- };
- let ans = new Array(n).fill(0);
- let visited = new Array(n).fill(0);
- let queue = [];
- let depth = 1;
+ const q: number[] = [];
+ const time: number[] = Array(n).fill(-1);
+ const force: string[][] = Array.from({ length: n }, () => []);
+
for (let i = 0; i < n; i++) {
- let cur = map[dominoes.charAt(i)];
- if (cur) {
- queue.push(i);
- visited[i] = depth;
- ans[i] = cur;
+ const f = dominoes[i];
+ if (f !== '.') {
+ q.push(i);
+ time[i] = 0;
+ force[i].push(f);
}
}
- while (queue.length) {
- depth++;
- let nextLevel = [];
- for (let i of queue) {
- const dx = ans[i];
- let x = i + dx;
- if (x >= 0 && x < n && [0, depth].includes(visited[x])) {
- ans[x] += dx;
- visited[x] = depth;
- nextLevel.push(x);
+
+ const ans: string[] = Array(n).fill('.');
+ let head = 0;
+ while (head < q.length) {
+ const i = q[head++];
+ if (force[i].length === 1) {
+ const f = force[i][0];
+ ans[i] = f;
+ const j = f === 'L' ? i - 1 : i + 1;
+ if (j >= 0 && j < n) {
+ const t = time[i];
+ if (time[j] === -1) {
+ q.push(j);
+ time[j] = t + 1;
+ force[j].push(f);
+ } else if (time[j] === t + 1) {
+ force[j].push(f);
+ }
}
}
- queue = nextLevel;
}
- return ans
- .map(d => {
- if (!d) return '.';
- else if (d < 0) return 'L';
- else return 'R';
- })
- .join('');
+ return ans.join('');
}
```
diff --git a/solution/0800-0899/0838.Push Dominoes/Solution.ts b/solution/0800-0899/0838.Push Dominoes/Solution.ts
index d9e8412c5d062..0b912d31ca203 100644
--- a/solution/0800-0899/0838.Push Dominoes/Solution.ts
+++ b/solution/0800-0899/0838.Push Dominoes/Solution.ts
@@ -1,41 +1,37 @@
function pushDominoes(dominoes: string): string {
const n = dominoes.length;
- const map = {
- L: -1,
- R: 1,
- '.': 0,
- };
- let ans = new Array(n).fill(0);
- let visited = new Array(n).fill(0);
- let queue = [];
- let depth = 1;
+ const q: number[] = [];
+ const time: number[] = Array(n).fill(-1);
+ const force: string[][] = Array.from({ length: n }, () => []);
+
for (let i = 0; i < n; i++) {
- let cur = map[dominoes.charAt(i)];
- if (cur) {
- queue.push(i);
- visited[i] = depth;
- ans[i] = cur;
+ const f = dominoes[i];
+ if (f !== '.') {
+ q.push(i);
+ time[i] = 0;
+ force[i].push(f);
}
}
- while (queue.length) {
- depth++;
- let nextLevel = [];
- for (let i of queue) {
- const dx = ans[i];
- let x = i + dx;
- if (x >= 0 && x < n && [0, depth].includes(visited[x])) {
- ans[x] += dx;
- visited[x] = depth;
- nextLevel.push(x);
+
+ const ans: string[] = Array(n).fill('.');
+ let head = 0;
+ while (head < q.length) {
+ const i = q[head++];
+ if (force[i].length === 1) {
+ const f = force[i][0];
+ ans[i] = f;
+ const j = f === 'L' ? i - 1 : i + 1;
+ if (j >= 0 && j < n) {
+ const t = time[i];
+ if (time[j] === -1) {
+ q.push(j);
+ time[j] = t + 1;
+ force[j].push(f);
+ } else if (time[j] === t + 1) {
+ force[j].push(f);
+ }
}
}
- queue = nextLevel;
}
- return ans
- .map(d => {
- if (!d) return '.';
- else if (d < 0) return 'L';
- else return 'R';
- })
- .join('');
+ return ans.join('');
}