4070. 拨号的最少旋转次数 I
来源第 522 场周赛 Q1难度简单分数1156
题目描述
给你一个长度为 10、由数字组成的字符串 s。
拨号盘上的数字 0 到 9 按顺序排列,且拨号盘是环形的,因此 0 和 9 相邻。指针最初指向 0。
要按顺序拨出 s 中的每个数字,需要旋转指针,直到它指向该数字。每次旋转都会将指针移动到一个相邻的数字,你可以向任一方向旋转。如果指针已经指向要拨出的数字,则无需旋转。
返回拨出 s 中所有数字所需的最少总旋转次数。
示例 1:
输入: s = "0192837465"
输出: 25
解释:
| 步骤 | 起始数字 | 目标数字 | 旋转次数 |
|---|---|---|---|
| 1 | 0 | 0 | 0 |
| 2 | 0 | 1 | 1 |
| 3 | 1 | 9 | 2 |
| 4 | 9 | 2 | 3 |
| 5 | 2 | 8 | 4 |
| 6 | 8 | 3 | 5 |
| 7 | 3 | 7 | 4 |
| 8 | 7 | 4 | 3 |
| 9 | 4 | 6 | 2 |
| 10 | 6 | 5 | 1 |
总旋转次数为 0 + 1 + 2 + 3 + 4 + 5 + 4 + 3 + 2 + 1 = 25,这是最少的总旋转次数。
示例 2:
输入: s = "1200210200"
输出: 12
解释:
| 步骤 | 起始数字 | 目标数字 | 旋转次数 |
|---|---|---|---|
| 1 | 0 | 1 | 1 |
| 2 | 1 | 2 | 1 |
| 3 | 2 | 0 | 2 |
| 4 | 0 | 0 | 0 |
| 5 | 0 | 2 | 2 |
| 6 | 2 | 1 | 1 |
| 7 | 1 | 0 | 1 |
| 8 | 0 | 2 | 2 |
| 9 | 2 | 0 | 2 |
| 10 | 0 | 0 | 0 |
总旋转次数为 1 + 1 + 2 + 0 + 2 + 1 + 1 + 2 + 2 + 0 = 12,这是最少的总旋转次数。
提示:
s.length == 10s仅由数字'0'到'9'组成
解法
方法一
思考
每次拨号只关心当前指针位置和目标数字,其余历史不会影响后续选择,因此可以按顺序贪心处理每一位。
从数字 \(a\) 转到数字 \(b\) 时,顺时针和逆时针两条路径的步数分别互补为 \(10\)。设两者的数字差为 \(d=|a-b|\),那么最少旋转次数就是 \(\min(d, 10-d)\)。
初始指针在 \(0\),依次累加相邻两次拨号之间的最小代价即可。
设上一位所在数字为 \(\textit{pre}\),当前要拨到的数字为 \(\textit{cur}\)。由于拨号盘是环形的,从 \(\textit{pre}\) 走到 \(\textit{cur}\) 的最短距离为
从初始位置 \(0\) 开始遍历字符串中的每个字符,计算这一段最短距离并累加到答案中,然后更新 \(\textit{pre}\) 即可。
时间复杂度 \(O(n)\),空间复杂度 \(O(1)\)。其中 \(n\) 为字符串 \(s\) 的长度。
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
1 2 3 4 5 6 7 8 9 10 11 | |