Categorygithub.com/szhou12/leetcode-goleetcode3122-Minimum-Number-of-Operations-to-Satisfy-Conditions
package
0.0.0-20241220224003-b7cf03a90b2b
Repository: https://github.com/szhou12/leetcode-go.git
Documentation: pkg.go.dev
# README
3122. Minimum Number of Operations to Satisfy Conditions
Solution idea
2-D DP
- 第一眼看过去,容易想到的是greedy algorithm: 先以列为单位,看每一列,找出频次最高的数,把其他数变成这个数。再以行为单位,调整使每相邻的数不同。但是,这样做有很多corner cases要处理。比如:1. 如果一列中所有数频次都相同选哪一个?2.先调整列再调整行会增加operation次数(因为看不到全局,本可以在调整列时就一次性完成的操作额外留到了调整行的步骤)
- 突破点: 看到题目的constraint
1 <= n, m <= 1000
。说明,每个格子一一看过去需要10^6
次操作,这是可以接受的。同时,0 <= grid[i][j] <= 9
暗示了如果枚举0~9
,时间复杂度在10^7
,刚刚好可以接受。所以,可能我们需要通过枚举来解决问题。正式的,每一列我们尝试枚举0~9
,看哪一个数要求的操作数最少。如何保证列与列之间的数不同?通过DP的转移方程来传递信息。 - Definition:
dp[i][p] := min operations to fill up first i cols with i-th col being set up with number p
i
: col numbers so far;p
: 0~9- Base case: 0-th col doesn't depend on previous cols. So
dp[0][p] = min ops of first 0 col = cost to set 0-th col to p
- Recurrence:
dp[i][p] = min{dp[i-1][q] + cost(i, p) for q=0..9} for p=0..9 and p!=q
- 可优化的地方:DP的解法中可优化,每一列不用枚举所有0~9,只用找出当前列频次最高,次高,第三高的三个数,枚举这三个数就可以。为什么?题目要求当前列与邻接的列的数不同。所以三个数足够找出一个数使其与左右两列的数不同,同时它的频次又是top 3,所以相较于其他频次低的数,它导致的操作数肯定更少。
Time complexity = $O(mn\cdot 10 \cdot 10)$
Resource
【每日一题】LeetCode 3122. Minimum Number of Operations to Satisfy Conditions