|
29 | 29 | <p>You are given a string <code>dominoes</code> representing the initial state where:</p>
|
30 | 30 |
|
31 | 31 | <ul>
|
32 |
| - <li><code>dominoes[i] = 'L'</code>, if the <code>i<sup>th</sup></code> domino has been pushed to the left,</li> |
33 |
| - <li><code>dominoes[i] = 'R'</code>, if the <code>i<sup>th</sup></code> domino has been pushed to the right, and</li> |
34 |
| - <li><code>dominoes[i] = '.'</code>, if the <code>i<sup>th</sup></code> domino has not been pushed.</li> |
| 32 | + <li><code>dominoes[i] = 'L'</code>, if the <code>i<sup>th</sup></code> domino has been pushed to the left,</li> |
| 33 | + <li><code>dominoes[i] = 'R'</code>, if the <code>i<sup>th</sup></code> domino has been pushed to the right, and</li> |
| 34 | + <li><code>dominoes[i] = '.'</code>, if the <code>i<sup>th</sup></code> domino has not been pushed.</li> |
35 | 35 | </ul>
|
36 | 36 |
|
37 | 37 | <p>Return <em>a string representing the final state</em>.</p>
|
|
56 | 56 | <p><strong>Constraints:</strong></p>
|
57 | 57 |
|
58 | 58 | <ul>
|
59 |
| - <li><code>n == dominoes.length</code></li> |
60 |
| - <li><code>1 <= n <= 10<sup>5</sup></code></li> |
61 |
| - <li><code>dominoes[i]</code> is either <code>'L'</code>, <code>'R'</code>, or <code>'.'</code>.</li> |
| 59 | + <li><code>n == dominoes.length</code></li> |
| 60 | + <li><code>1 <= n <= 10<sup>5</sup></code></li> |
| 61 | + <li><code>dominoes[i]</code> is either <code>'L'</code>, <code>'R'</code>, or <code>'.'</code>.</li> |
62 | 62 | </ul>
|
63 | 63 |
|
64 | 64 | <!-- description:end -->
|
|
67 | 67 |
|
68 | 68 | <!-- solution:start -->
|
69 | 69 |
|
70 |
| -### Solution 1 |
| 70 | +### Solution 1: Multi-Source BFS |
| 71 | + |
| 72 | +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, ...): |
| 73 | + |
| 74 | +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. |
| 75 | + |
| 76 | +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: |
| 77 | + |
| 78 | +$$ |
| 79 | +j = |
| 80 | +\begin{cases} |
| 81 | +i - 1, & f = L,\\ |
| 82 | +i + 1, & f = R. |
| 83 | +\end{cases} |
| 84 | +$$ |
| 85 | + |
| 86 | +If $0 \leq j < n$: |
| 87 | + |
| 88 | +- 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]}$. |
| 89 | +- 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. |
| 90 | + |
| 91 | +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. |
| 92 | + |
| 93 | +The complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the number of dominoes. |
71 | 94 |
|
72 | 95 | <!-- tabs:start -->
|
73 | 96 |
|
@@ -241,44 +264,40 @@ func pushDominoes(dominoes string) string {
|
241 | 264 | ```ts
|
242 | 265 | function pushDominoes(dominoes: string): string {
|
243 | 266 | const n = dominoes.length;
|
244 |
| - const map = { |
245 |
| - L: -1, |
246 |
| - R: 1, |
247 |
| - '.': 0, |
248 |
| - }; |
249 |
| - let ans = new Array(n).fill(0); |
250 |
| - let visited = new Array(n).fill(0); |
251 |
| - let queue = []; |
252 |
| - let depth = 1; |
| 267 | + const q: number[] = []; |
| 268 | + const time: number[] = Array(n).fill(-1); |
| 269 | + const force: string[][] = Array.from({ length: n }, () => []); |
| 270 | + |
253 | 271 | for (let i = 0; i < n; i++) {
|
254 |
| - let cur = map[dominoes.charAt(i)]; |
255 |
| - if (cur) { |
256 |
| - queue.push(i); |
257 |
| - visited[i] = depth; |
258 |
| - ans[i] = cur; |
| 272 | + const f = dominoes[i]; |
| 273 | + if (f !== '.') { |
| 274 | + q.push(i); |
| 275 | + time[i] = 0; |
| 276 | + force[i].push(f); |
259 | 277 | }
|
260 | 278 | }
|
261 |
| - while (queue.length) { |
262 |
| - depth++; |
263 |
| - let nextLevel = []; |
264 |
| - for (let i of queue) { |
265 |
| - const dx = ans[i]; |
266 |
| - let x = i + dx; |
267 |
| - if (x >= 0 && x < n && [0, depth].includes(visited[x])) { |
268 |
| - ans[x] += dx; |
269 |
| - visited[x] = depth; |
270 |
| - nextLevel.push(x); |
| 279 | + |
| 280 | + const ans: string[] = Array(n).fill('.'); |
| 281 | + let head = 0; |
| 282 | + while (head < q.length) { |
| 283 | + const i = q[head++]; |
| 284 | + if (force[i].length === 1) { |
| 285 | + const f = force[i][0]; |
| 286 | + ans[i] = f; |
| 287 | + const j = f === 'L' ? i - 1 : i + 1; |
| 288 | + if (j >= 0 && j < n) { |
| 289 | + const t = time[i]; |
| 290 | + if (time[j] === -1) { |
| 291 | + q.push(j); |
| 292 | + time[j] = t + 1; |
| 293 | + force[j].push(f); |
| 294 | + } else if (time[j] === t + 1) { |
| 295 | + force[j].push(f); |
| 296 | + } |
271 | 297 | }
|
272 | 298 | }
|
273 |
| - queue = nextLevel; |
274 | 299 | }
|
275 |
| - return ans |
276 |
| - .map(d => { |
277 |
| - if (!d) return '.'; |
278 |
| - else if (d < 0) return 'L'; |
279 |
| - else return 'R'; |
280 |
| - }) |
281 |
| - .join(''); |
| 300 | + return ans.join(''); |
282 | 301 | }
|
283 | 302 | ```
|
284 | 303 |
|
|
0 commit comments