Categorygithub.com/szhou12/leetcode-goleetcode1769-Minimum-Number-of-Operations-to-Move-All-Balls-to-Each-Box
package
0.0.0-20241220224003-b7cf03a90b2b
Repository: https://github.com/szhou12/leetcode-go.git
Documentation: pkg.go.dev
# README
1769. Minimum Number of Operations to Move All Balls to Each Box
Solution idea
Naive Solution
遍历分界点, 每个点都分别看一下左手边总共多少moves,右手边总共多少moves
Time complexity = $O(n^2)$
3-Pass
要点总结
- 优化思路: 注意到遍历每一个分界点时,不需要重新把每个ball还原到它原来的位子再开始计算移动所用moves。直接继承移动ball到之前一个点的位置所用moves,再+1就行了 (
DP
思想)
物理意义
Note: n=len(boxes)
Note: 为了容易理解,这里提及的 [x:y]
都是左闭右闭
leftMoves[i] := # of moves to move all balls in boxes[0:i-1] to cell i
Base case:
leftMoves[0] = 0 // 最左边没有ball可以移动,显然也就没有moves
Recurrence:
leftMoves[i] = leftMoves[i-1] + left[i]*1
left[i] := total # of balls in boxes[0:i-1] // i位置的左边有多少个ball, 有ball才需要移动, 没有就不用管
Base case:
left[0] = 0
Recurrence:
left[i] = left[i-1] + 1 if boxes[i-1] == 1
= left[i-1] 0/w
// 显然, left[]是可以用一个标量left简化, 实现时不需要array left[]
rightMoves[i] := # of moves to move all balls in boxes[i+1:n-1] to cell i
Base case:
rightMoves[n-1] = 0 // 最右边没有ball可以移动,显然也就没有moves
Recurrence:
rightMoves[i] = rightMoves[i+1] + right[i]*1
right[i] := total # of balls in boxes[i+1:n-1] // i位置的右边有多少个ball, 有ball才需要移动, 没有就不用管
Base case:
right[n-1] = 0
Recurrence:
right[i] = right[i+1] + 1 if boxes[i+1] == 1
= right[i+1] 0/w
// 显然, right[]是可以用一个标量right简化, 实现时不需要array right[]
代码整体结构总结
Step 1: 构造 leftMoves[]
Step 2: 构造 rightMoves[]
Step 3: iterate 分界点, 每个点计算`leftMoves[i]+rightMoves[i]`
Time complexity = $O(n)$
Resource
【每日一题】1769. Minimum Number of Operations to Move All Balls to Each Box, 2/24/2021