LeetCode每日一题2025-05-03
1007. 行相等的最少多米诺旋转 M
在一排多米诺骨牌中,tops[i] 和 bottoms[i] 分别代表第 i 个多米诺骨牌的上半部分和下半部分。(一个多米诺是两个从 1 到 6 的数字同列平铺形成的 —— 该平铺的每一半上都有一个数字。)
我们可以旋转第 i 张多米诺,使得 tops[i] 和 bottoms[i] 的值交换。
返回能使 tops 中所有值或者 bottoms 中所有值都相同的最小旋转次数。
如果无法做到,返回 -1.
示例 1:

输入:tops = [2,1,2,4,2,2], bottoms = [5,2,6,2,3,2]
输出:2
解释:
图一表示:在我们旋转之前, tops 和 bottoms 给出的多米诺牌。
如果我们旋转第二个和第四个多米诺骨牌,我们可以使上面一行中的每个值都等于 2,如图所示。
示例 2:
输入:tops = [3,5,1,2,3], bottoms = [3,6,3,3,4]
输出:-1
解释: 在这种情况下,不可能旋转多米诺牌使一行的值相等。
提示:
2 <= tops.length <= 2 * 10⁴bottoms.length == tops.length1 <= tops[i], bottoms[i] <= 6
问题分析
给定两条长度相同的数组 tops 和 bottoms,表示一排多米诺骨牌的上下数字。你可以对任意一张牌做“旋转”操作(即上下数字交换位置)。目标是让 整条“上行” 或 整条“下行” 的数字都相同,求所需的最少旋转次数;如果做不到,则返回 -1。
算法思路
假设最终我们要把上行全部变成某个数字 x。那么对于第 1 张牌,它转前在上行是 tops[0],转后可能是拿下面的 bottoms[0] 过来。
- 如果最终目标行全是
x,第 1 张牌要么原本上面就是x(即tops[0] == x),要么通过旋转后上面成为bottoms[0] == x。 - 因此,唯一可能的候选
x就是{ tops[0], bottoms[0] }两个值之一。 - 其它任何值作为目标,都不可能同时兼顾第 1 张牌。
时间复杂度
时间复杂度:,其中 是多米诺数量。至多对两个候选各做一次「线性遍历」。
空间复杂度:,只用了常数级额外变量(两个计数器和一个候选集合)。
代码分解
-
确定候选目标值
只可能让最终整行相同的值是第一张牌上或下的数字,记为x1 = tops[0]、x2 = bottoms[0]。 -
对每个候选值 x,遍历整排牌
- 用两个计数器
rot_top和rot_bot分别记录:rot_top:若想让 上行tops 全部变为x,需要旋转的次数;rot_bot:若想让 下行bottoms 全部变为x,需要旋转的次数。
- 遍历索引
i,对每一张牌:- 若
tops[i]≠x且bottoms[i]≠x,说明这张牌无论如何(原地或旋转)都无法在上行或下行出现x,立即返回不可行(记为无穷大,最后结果取最小会被过滤)。 - 否则:
- 想让上行变成 x:如果
tops[i]≠x,则必须旋转这一张,令rot_top++。 - 想让下行变成 x:如果
bottoms[i]≠x,则必须旋转这一张,令rot_bot++。
- 想让上行变成 x:如果
- 若
- 用两个计数器
-
取两条方案中的最小值
- 对候选
x1、x2分别计算后(要么把上行全换成x,需要rot_top次旋转;
要么把下行全换成x,需要rot_bot次旋转), - 答案为其中较小的旋转次数;
- 若都是无穷大,则返回
-1。
- 对候选
-
小结
- 从
{ tops[0], bottoms[0] }中拿到至多两个候选x。 - 对每个候选值调用上面“检查并计数”逻辑,得到一个旋转次数(或“无解”标记)。
- 在这两个结果中取最小,若都是“无解”,则返回 -1,否则返回该最小值。
- 从
代码实现
1 | from typing import List |
以 tops = [2,1,2,4,2,2],bottoms = [5,2,6,2,3,2] 为例:
- 候选集合:
{ 2, 5 }
试 x = 2
| i | tops[i] | bottoms[i] | tops[i]==2? | bottoms[i]==2? | rot_top 增量 | rot_bot 增量 |
|---|---|---|---|---|---|---|
| 0 | 2 | 5 | 是 | 否 | 0 | 1 |
| 1 | 1 | 2 | 否 | 是 | 1 | 0 |
| 2 | 2 | 6 | 是 | 否 | 0 | 1 |
| 3 | 4 | 2 | 否 | 是 | 1 | 0 |
| 4 | 2 | 3 | 是 | 否 | 0 | 1 |
| 5 | 2 | 2 | 是 | 是 | 0 | 0 |
| 合计 | 2 | 3 |
试 x = 5
检查到 tops[1]=1 且 bottoms[1]=2 都不是 5,立即判定无解(记作 ∞)。
最终在 {2, ∞} 中取最小,就是 2。