723 粉碎糖果

题目描述:
这个问题是实现一个简单的消除算法。
给定一个二维整数数组 board 代表糖果所在的方格,不同的正整数 board[i][j] 代表不同种类的糖果,如果 board[i][j] = 0 代表 (i, j) 这个位置是空的。给定的方格是玩家移动后的游戏状态,现在需要你根据以下规则粉碎糖果,使得整个方格处于稳定状态并最终输出。
如果有三个及以上水平或者垂直相连的同种糖果,同一时间将它们粉碎,即将这些位置变成空的。
在同时粉碎掉这些糖果之后,如果有一个空的位置上方还有糖果,那么上方的糖果就会下落直到碰到下方的糖果或者底部,这些糖果都是同时下落,也不会有新的糖果从顶部出现并落下来。
通过前两步的操作,可能又会出现可以粉碎的糖果,请继续重复前面的操作。
当不存在可以粉碎的糖果,也就是状态稳定之后,请输出最终的状态。
你需要模拟上述规则并使整个方格达到稳定状态,并输出。

样例 :
输入:
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]]

输出:
[[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]]

解释:
在这里插入图片描述
注释 :
board 数组的行数区间是 [3, 50]。
board[i] 数组的长度区间(即 board 数组的列数区间)是 [3, 50]。
每个 board[i][j] 初始整数范围是 [1, 2000]。

方法1:
主要思路:
(1)使用两个辅助函数,第一个find_pos函数用来找可以粉碎的糖果的位置,这里函数内将找行和列分开进行;
(2)第二个辅助函数updata用来将找到的需要粉碎的位置进行更新,获得新的数组组成;
(3)再重复调用这两个函数,直到第一个函数内找不到需要粉碎的位置;

class Solution {
public:
	//找需要粉碎的位置
    void find_pos(vector<vector<int>>& board,bool& sign){
    	//先在每行中找需要粉碎糖果的位置
        for(int i=0;i<board.size();++i){
            for(int j=0;j<board[0].size()-2;++j){
                if(board[i][j]!=0){
                    int cur_pos=j;
                    while(cur_pos<board[0].size()&&board[i][cur_pos]==board[i][j]){
                        ++cur_pos;
                    }
                    if(cur_pos-j>=3){//判断是否找到合适的需要粉碎的位置
                        sign=true;
                        while(j<cur_pos){//将需要粉碎的位置进行负数标识
                            board[i][j]=-board[i][j];
                            ++j;
                        }
                        --j;
                    }
                }
            }
        }
		//再在每列中找需要粉碎糖果的位置
        for(int i=0;i<board[0].size();++i){
            for(int j=0;j<board.size()-2;++j){
                if(board[j][i]!=0){
                    int cur_pos=j;
                    while(cur_pos<board.size()&&abs(board[cur_pos][i])==abs(board[j][i])){//上面在行中,已经使用了负数进行标识
                        ++cur_pos;
                    }
                    if(cur_pos-j>=3){
                        sign=true;
                        while(j<cur_pos){
                            board[j][i]=-abs(board[j][i]);//将位置上的数字使用负数进行标识
                            ++j;
                        }
                        --j;
                    }
                }
            }
        }
    }
    //将标识的位置进行更细
    void updata(vector<vector<int>>&board){
    	//对每列从下向上进行更新
        for(int col=0;col<board[0].size();++col){
            int cur_pos=board.size();
            for(int row=board.size()-1;row>=0;--row){
                if(board[row][col]>0){
                    board[--cur_pos][col]=board[row][col];
                }
            }
            //将当前列的上面的位置进行赋值0
            while(cur_pos>0){
                board[--cur_pos][col]=0;
            }
        }
    }
    vector<vector<int>> candyCrush(vector<vector<int>>& board) {
        bool sign=false;
        while(true){
            sign=false;
            find_pos(board,sign);
            if(!sign){//说明没再找到可以粉碎的位置,故需要跳出循环
                break;
            }
            updata(board);
        }
        return board;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值