This question is about implementing a basic elimination algorithm for Candy Crush.

Given a 2D integer array board representing the grid of candy, different positive integers board[i][j] represent different types of candies. A value of board[i][j] = 0 represents that the cell at position (i, j) is empty. The given board represents the state of the game following the player's move. Now, you need to restore the board to a stable state by crushing candies according to the following rules:

  1. If three or more candies of the same type are adjacent vertically or horizontally, "crush" them all at the same time - these positions become empty.
  2. After crushing all candies simultaneously, if an empty space on the board has candies on top of itself, then these candies will drop until they hit a candy or bottom at the same time. (No new candies will drop outside the top boundary.)
  3. After the above steps, there may exist more candies that can be crushed. If so, you need to repeat the above steps.
  4. If there does not exist more candies that can be crushed (ie. the board is stable), then return the current board.

You need to perform the above rules until the board becomes stable, then return the current board.

Example 1:

Input:
board =
[[110,5,112,113,114],[210,211,5,213,214],[310,311,3,313,314],[410,411,412,5,414],[5,1,512,3,3],[610,4,1,613,614],[710,1,2,713,714],[810,1,2,1,1],[1,1,2,2,2],[4,1,4,4,1014]]
Output:
[[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[110,0,0,0,114],[210,0,0,0,214],[310,0,0,113,314],[410,0,0,213,414],[610,211,112,313,614],[710,311,412,613,714],[810,411,512,713,1014]]
Explanation:

Note:

  1. The length of board will be in the range [3, 50].
  2. The length of board[i] will be in the range [3, 50].
  3. Each board[i][j] will initially start as an integer in the range [1, 2000].

这道题就是糖果消消乐,博主刚开始做的时候,没有看清楚题意,以为就像游戏中的那样,每次只能点击一个地方,然后消除后糖果落下,这样会导致一个问题,就是原本其他可以消除的地方在糖果落下后可能就没有了,所以博主在想点击的顺序肯定会影响最终的 stable 的状态,可是题目怎么没有要求返回所剩糖果最少的状态?后来发现,其实这道题一次消除 table 中所有可消除的糖果,然后才下落,形成新的 table,这样消除后得到的结果就是统一的了,这样也大大的降低了难度。下面就来看如何找到要消除的糖果,可能有人会觉得像之前的岛屿的题目一样找连通区域,可是这道题的有限制条件,只有横向或竖向相同的糖果数达到三个才能消除,并不是所有的连通区域都能消除,所以找连通区域不是一个好办法。最好的办法其实是每个糖果单独检查其是否能被消除,然后把所有能被删除的糖果都标记出来统一删除,然后在下落糖果,然后再次查找,直到无法找出能够消除的糖果时达到稳定状态。好,用一个数组来保存可以被消除的糖果的位置坐标,判断某个位置上的糖果能否被消除的方法就是检查其横向和纵向的最大相同糖果的个数,只要有一个方向达到三个了,当前糖果就可以被消除。所以对当前糖果的上下左右四个方向进行查看,用四个变量 x0, x1, y0, y1,其中 x0 表示上方相同的糖果的最大位置,x1 表示下方相同糖果的最大位置,y0 表示左边相同糖果的最大位置,y1 表示右边相同糖果的最大位置,均初始化为当前糖果的位置,然后使用 while 循环向每个方向遍历,注意并不需要遍历到尽头,而是只要遍历三个糖果就行了,因为一旦查到了三个相同的,就说明当前的糖果已经可以消除了,没必要再往下查了。查的过程还要注意处理越界情况,好,得到了上下左右的最大的位置,分别让相同方向的做差,如果水平和竖直方向任意一个大于3了,就说明可以消除,将坐标加入数组 del 中。注意这里一定要大于3,是因为当发现不相等退出 while 循环时,坐标值已经改变了,所以已经多加了或者减了一个,所以差值要大于3。遍历完成后,如果数组 del 为空,说明已经 stable 了,直接 break 掉,否则将要消除的糖果位置都标记为0,然后进行下落处理。下落处理实际上是把数组中的0都移动到开头,那么就从数组的末尾开始遍历,用一个变量t先指向末尾,然后然后当遇到非0的数,就将其和t位置上的数置换,然后t自减1,这样t一路减下来都是非0的数,而0都被置换到数组开头了,参见代码如下:

class Solution {
public:
vector<vector<int>> candyCrush(vector<vector<int>>& board) {
int m = board.size(), n = board[].size();
while (true) {
vector<pair<int, int>> del;
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (board[i][j] == ) continue;
int x0 = i, x1 = i, y0 = j, y1 = j;
while (x0 >= && x0 > i - && board[x0][j] == board[i][j]) --x0;
while (x1 < m && x1 < i + && board[x1][j] == board[i][j]) ++x1;
while (y0 >= && y0 > j - && board[i][y0] == board[i][j]) --y0;
while (y1 < n && y1 < j + && board[i][y1] == board[i][j]) ++y1;
if (x1 - x0 > || y1 - y0 > ) del.push_back({i, j});
}
}
if (del.empty()) break;
for (auto a : del) board[a.first][a.second] = ;
for (int j = ; j < n; ++j) {
int t = m - ;
for (int i = m - ; i >= ; --i) {
if (board[i][j]) swap(board[t--][j], board[i][j]);
}
}
}
return board;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/723

参考资料:

https://leetcode.com/problems/candy-crush/

https://leetcode.com/problems/candy-crush/discuss/178366/Another-Java-Solution

https://leetcode.com/problems/candy-crush/discuss/109225/Simple-C%2B%2B-brute-force

https://leetcode.com/problems/candy-crush/discuss/113914/15-ms-Short-Java-Solution-Mark-crush-with-negative-value

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Candy Crush 糖果消消乐的更多相关文章

  1. [LeetCode] Candy (分糖果),时间复杂度O(n),空间复杂度为O(1),且只需遍历一次的实现

    [LeetCode] Candy (分糖果),时间复杂度O(n),空间复杂度为O(1),且只需遍历一次的实现 原题: There are N children standing in a line. ...

  2. [LeetCode] 723. Candy Crush 糖果消消乐

    This question is about implementing a basic elimination algorithm for Candy Crush. Given a 2D intege ...

  3. [LeetCode] 723. Candy Crush 糖果粉碎

    This question is about implementing a basic elimination algorithm for Candy Crush. Given a 2D intege ...

  4. [LeetCode] Candy 分糖果问题

    There are N children standing in a line. Each child is assigned a rating value. You are giving candi ...

  5. 消消乐、candy crush类三消游戏程序逻辑分析

    最近在开发一款类似消消乐的三消游戏,在碰到实现斜方向下落的时候卡住了很长时间.好几天没有思路,原本的思路是一次性预判多个宝石的一连串运动路径,运用缓动运动队列来实现宝石运动路径,例如 下落->滑 ...

  6. 【LeetCode】723. Candy Crush 解题报告 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力 日期 题目地址:https://leetcode ...

  7. net.sz.framework 框架 ORM 消消乐超过亿条数据排行榜分析 天王盖地虎

    序言 天王盖地虎, 老婆马上生孩子了,在家待产,老婆喜欢玩消消乐类似的休闲游戏,闲置状态,无聊的分析一下消消乐游戏的一些技术问题: 由于我主要是服务器研发,客户端属于半吊子,所以就分析一下消消乐排行榜 ...

  8. RSP小组——消消乐

    RSP小组--消消乐 团队所有博客总结 1.团队第一周作业 2.团队第二周作业 3.RSP小组--团队冲刺博客一 4.RSP小组--团队冲刺博客二 5.RSP小组--团队冲刺博客三 6.RSP小组-- ...

  9. PHP实现开心消消乐的算法示例

    本文主要介绍了关于PHP如何实现我们大家都知道的开心消消乐的算法,分享PHP教程出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 一.需求描述:      1.在一个8*8的矩阵方格中随机 ...

随机推荐

  1. java开发常用技术

    基础部分 1. 线程和进程的区别 线程三个基本状态:就绪.执行.阻塞 线程五个基本操作:创建.就绪.运行.阻塞.终止 进程四种形式:主从式.会话式.消息或邮箱机制.共享存储区方式 进程是具有一定功能的 ...

  2. MongoDb进阶实践之三 Mongodb基本命令详解

    一.引言              从今天开始,我要正式开始介绍MongoDB的使用方法了.在此之前,我用了两篇文章分别介绍了如何在Linux系统和Windows系统上安装和配置MongoDB系统.如 ...

  3. ResultSet的getInt()和getString()方法详解

     数据库tt的examstudent数据表如下:   在MySQL中执行查询语句如下: ResultSet rs = null; String sql="SELECT flow_id,Typ ...

  4. 腾讯云python网站开发环境搭建

    前段时间腾讯云做活动,于是就花了几百大洋买了三年的云服务,准备在上 面安装python web的开发环境,下面将安装过程做一个总结,希望能够帮助大家. 一.使用环境   使用的软件环境为:CentOS ...

  5. drbd(三):drbd的状态说明

    本文目录:1.drbd配置文件2.状态 2.1 连接状态(connect state,cs)和复制状态 2.2 角色状态(roles,ro) 2.3 磁盘状态(disk state,ds) 2.4 I ...

  6. hibernate框架学习笔记8:一对多关系案例

    两个实体类:客户与联系人,一个客户可以有多个联系人 客户类: package domain; import java.util.HashSet; import java.util.Set; //客户实 ...

  7. 关于如何学习C语言

    2016级计算机专业的C语言分为两个学期,第一学期是C语言(基础),第二学期是C语言(高级),在第一学期主要学习的内容是基本的数据类型,分支结构和循环结构,一维和二维数组,字符数组,函数.通过这学期独 ...

  8. io多路复用(三)

    #!/usr/bin/env python # -*- coding:utf-8 -*- import socket sk1 = socket.socket() sk1.bind(('127.0.0. ...

  9. Scrum 冲刺 第五日

    目录 要求 项目链接 燃尽图 问题 今日任务 明日计划 成员贡献量 要求 各个成员今日完成的任务(如果完成的任务为开发或测试任务,需给出对应的Github代码签入记录截图:如果完成的任务为调研任务,需 ...

  10. 【iOS】swift 74个Swift标准库函数

    本文译自 Swift Standard Library: Documented and undocumented built-in functions in the Swift standard li ...