|
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