|
| 1 | +## 题目地址(488. 祖玛游戏) |
| 2 | + |
| 3 | +https://leetcode-cn.com/problems/zuma-game/ |
| 4 | + |
| 5 | +## 题目描述 |
| 6 | + |
| 7 | +``` |
| 8 | +回忆一下祖玛游戏。现在桌上有一串球,颜色有红色(R),黄色(Y),蓝色(B),绿色(G),还有白色(W)。 现在你手里也有几个球。 |
| 9 | +
|
| 10 | +每一次,你可以从手里的球选一个,然后把这个球插入到一串球中的某个位置上(包括最左端,最右端)。接着,如果有出现三个或者三个以上颜色相同的球相连的话,就把它们移除掉。重复这一步骤直到桌上所有的球都被移除。 |
| 11 | +
|
| 12 | +找到插入并可以移除掉桌上所有球所需的最少的球数。如果不能移除桌上所有的球,输出 -1 。 |
| 13 | +
|
| 14 | +示例: |
| 15 | +输入: "WRRBBW", "RB" |
| 16 | +输出: -1 |
| 17 | +解释: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WW (翻译者标注:手上球已经用完,桌上还剩两个球无法消除,返回-1) |
| 18 | +
|
| 19 | +输入: "WWRRBBWW", "WRBRW" |
| 20 | +输出: 2 |
| 21 | +解释: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> empty |
| 22 | +
|
| 23 | +输入:"G", "GGGGG" |
| 24 | +输出: 2 |
| 25 | +解释: G -> G[G] -> GG[G] -> empty |
| 26 | +
|
| 27 | +输入: "RBYYBBRRB", "YRBGB" |
| 28 | +输出: 3 |
| 29 | +解释: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty |
| 30 | +标注: |
| 31 | +
|
| 32 | +你可以假设桌上一开始的球中,不会有三个及三个以上颜色相同且连着的球。 |
| 33 | +桌上的球不会超过20个,输入的数据中代表这些球的字符串的名字是 "board" 。 |
| 34 | +你手中的球不会超过5个,输入的数据中代表这些球的字符串的名字是 "hand"。 |
| 35 | +输入的两个字符串均为非空字符串,且只包含字符 'R','Y','B','G','W'。 |
| 36 | +
|
| 37 | +
|
| 38 | +``` |
| 39 | + |
| 40 | +## 前置知识 |
| 41 | + |
| 42 | +- 回溯 |
| 43 | +- 哈希表 |
| 44 | +- 双指针 |
| 45 | + |
| 46 | +## 公司 |
| 47 | + |
| 48 | +- 百度 |
| 49 | + |
| 50 | +## 思路 |
| 51 | + |
| 52 | +面试题困难难度的题目常见的题型有: |
| 53 | + |
| 54 | +- DP |
| 55 | +- 设计题 |
| 56 | +- 图 |
| 57 | +- 游戏 |
| 58 | + |
| 59 | +本题就是游戏类题目。 如果你是一个前端, 说不定还会考察你如何实现一个 zuma 游戏。这种游戏类的题目,可以简单可以困难, 比如力扣经典的石子游戏,宝石游戏等。这类题目没有固定的解法。我做这种题目的思路就是先暴力模拟,再尝试优化算法瓶颈。 |
| 60 | + |
| 61 | +注意下数据范围球的数目 <= 5,因此暴力法就变得可行。基本思路是暴力枚举手上的球可以消除的地方, 我们可以使用回溯法来完成暴力枚举的过程,在回溯过程记录最小值即可。由于回溯树的深度不会超过 5,因此这种解法应该可以 AC。 |
| 62 | + |
| 63 | +上面提到的`可以消除的地方`,指的是**连续相同颜色 + 手上相同颜色的球大于等于 3**,这也是题目说明的消除条件。 |
| 64 | + |
| 65 | +因此我们只需要两个指针记录连续相同颜色球的位置,如果可以消除,消除即可。 |
| 66 | + |
| 67 | + |
| 68 | + |
| 69 | +如图,我们记录了连续红球的位置, 如果手上有红球, 则可以尝试将其清除,这一次决策就是回溯树(决策树)的一个分支。之后我们会撤回到这个决策分支, 尝试其他可行的决策分支。 |
| 70 | + |
| 71 | +以 board = RRBBRR , hand 为 RRBB 为例,其决策树为: |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +其中虚线表示无需手动干预,系统自动消除。叶子节点末尾的黄色表示全部消除需要的手球个数。路径上的文字后面的数字表示此次消除需要的手球个数 |
| 76 | + |
| 77 | +> 如果你对回溯不熟悉,可以参考下我之前写的几篇题解:比如 [46.permutations](https://github.com/azl397985856/leetcode/blob/master/problems/46.permutations.md "46.permutations")。 |
| 78 | +
|
| 79 | +可以看出, 如果选择先消除中间的蓝色,则只需要一步即可完成。 |
| 80 | + |
| 81 | +关于计算连续球位置的核心代码(Python3): |
| 82 | + |
| 83 | +```python |
| 84 | +i = 0 |
| 85 | +while i < len(board): |
| 86 | + j = i + 1 |
| 87 | + while j < len(board) and board[i] == board[j]: j += 1 |
| 88 | + # 其他逻辑 |
| 89 | + |
| 90 | + # 更新左指针 |
| 91 | + i = j |
| 92 | +``` |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | +具体算法: |
| 97 | + |
| 98 | +1. 用哈希表存储手上的球的种类和个数,这么做是为了后面**快速判断连续的球是否可以被消除**。由于题目限制手上求不会超过 5,因此哈希表的最大容量就是 5,可以认为这是一个常数的空间。 |
| 99 | +2. 回溯。 |
| 100 | + |
| 101 | + 2.1 确认可以消除的位置,算法参考上面的代码。 |
| 102 | + |
| 103 | + 2.2 判断手上是否有足够相同颜色的球可以消除。 |
| 104 | + |
| 105 | + 2.3 回溯的过程记录全局最小值。 |
| 106 | + |
| 107 | +## 代码 |
| 108 | + |
| 109 | +代码支持:Python3 |
| 110 | + |
| 111 | +Python3 Code: |
| 112 | + |
| 113 | +```python |
| 114 | +class Solution: |
| 115 | + def findMinStep(self, board: str, hand: str) -> int: |
| 116 | + def backtrack(board): |
| 117 | + if not board: return 0 |
| 118 | + i = 0 |
| 119 | + ans = 6 |
| 120 | + while i < len(board): |
| 121 | + j = i + 1 |
| 122 | + while j < len(board) and board[i] == board[j]: j += 1 |
| 123 | + balls = 3 - (j - i) |
| 124 | + if counter[board[i]] >= balls: |
| 125 | + balls = max(0, balls) |
| 126 | + counter[board[i]] -= balls |
| 127 | + ans = min(ans, balls + backtrack(board[:i] + board[j:])) |
| 128 | + counter[board[i]] += balls |
| 129 | + i = j |
| 130 | + return ans |
| 131 | + |
| 132 | + counter = collections.Counter(hand) |
| 133 | + ans = backtrack(board) |
| 134 | + return -1 if ans > 5 else ans |
| 135 | + |
| 136 | +``` |
| 137 | + |
| 138 | +**复杂度分析** |
| 139 | + |
| 140 | +- 时间复杂度:$O(2^(min(C, 5)))$,其中 C 为连续相同颜色球的次数,比如 WWRRRR, C 就是 2, WRBDD, C 就是 4。min(C, 5) 是因为题目限定了手上球的个数不大于 5。 |
| 141 | +- 空间复杂度:$O(min(C, 5) * Board)$,其中 C 为连续相同颜色球的次数,Board 为 Board 的长度。 |
| 142 | + |
| 143 | +## 关键点解析 |
| 144 | + |
| 145 | +- 回溯模板 |
| 146 | +- 双指针写法 |
| 147 | + |
| 148 | +大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 36K star 啦。 |
| 149 | +大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。 |
| 150 | + |
| 151 | + |
0 commit comments