LeetCode 994.腐烂的橘子(C语言)

994.腐烂的橘子

Description


在给定的网格中,每个单元格可以有以下三个值之一:

  • 值 0 代表空单元格;
  • 值 1 代表新鲜橘子;
  • 值 2 代表腐烂的橘子。

每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1。

Analyze


题目很好理解,就是给定一个二维数组代表网格,每个网格中放一个整数,0,1或者2,含义如题,其中为2的网格可以腐蚀1所在的网格(前提是1在2的旁边),求经过多少时间所有的1都变成了2,返回这个时间,如果不能完全腐蚀返回-1。
题中给定的函数是这样的:



初看到这个函数的时候是有点懵的,因为看它的测试用例输入只有一个二维数组,虽然看名字可以知道是两个长度,但具体又不知道是什么长度,费了一点时间才搞清楚这几个参数:

  • @param grid 一个二维数组
  • @param gridSize 二维数组的行数
  • @param gridColSize 二维数组每一行的列数

是的,最后一个数组表示的是每一行的列数,看这题目的意思是给定的数组行和列是不等的啊,那这题难度居然标的是easy,但实际上呢?实际提交之后发现每一行的列数都是相等的,即gridColSize[i] == gridColSize[0]

明白了函数之后就可以开始做题了,题目思路很明确,查看数组中所有为2的网格,将其附近(上下左右)网格为1的全部变为2,重复直到所有的2附近都没有了1,最后检查数组看是否还存在1的网格,不存在则返回改变的次数(这里的次数指的是每查看一轮数组,这一轮所有的1变为2后代表一次);存在则返回-1。

按照这个思路实现起来发现有点复杂,因为每一次都要遍历所有网格寻找2,实际上是根本不需要的,仔细想想会知道,第一次查看之后确定了2所在网格的坐标,然后将其附近的1变为2,那么之前找到的2的网格坐标其实已经没用了,因为他们的附近已经没有1的网格了。

2 1 1
1 1 0
1 0 1

比如给定上述二维数组,第一次查到(0,0)坐标为2,第一次改变会把(0,1),(1,0)两个网格的1变为2,此时一开始的(0,0)已经没有用了,可以扔掉,第二次查看的时候只要看(0,1)和(1,0)附近的网格就行了。

那怎么才能保存之后的坐标而把之前的坐标给扔掉呢,换一种说法就明白了:要把后进来的保留,先进来的先剔除。即先进先出,这很明显是队列的特性。因此,我们创建一个队列来保存这一轮所找到的网格为2的坐标。在此之前我们还有几个问题没有解决:

  • 用什么保存坐标?
  • 怎么判断次数(即怎么给出最后的时间)?

要保存坐标很简单,无非就是用两个整数,但考虑到我们一次可能需要保存很多点的坐标,而且我们还要创建队列,因此,可以定义一个结构体,把需要入队列的每个点的坐标当成结构体中的两个元素,这样方便引用。
那么怎么判断次数呢?可以给每个入队列的元素带一个标志,这个标志显示了它是第几轮被腐烂的,使用时只要把队列最后一个元素取出来看看它的标志就知道是第几次了。所以最后的结构体是这样的:

  • 包含三个整数,坐标x, y,和此坐标被腐烂时的次数

Realization


  • 遍历数组,找到所有的网格为2的坐标并且入队列


  • 取出队头元素,判断附近是否有1的网格,如果有,入队列

  • 遍历数组,若还存在1的网格,返回-1,否则返回result
  • 提交


Dictionary


上述的 gridColSize[i] 可以全部改成 gridColSize[0] ,因为LeetCode的测试用例的列数全都相同,如果列数不相同的话,需要在主要算法中加入一些判断边界的条件,比如判断一个"烂橘子"的右边时不能以小于 gridColSize[0] 为边界条件了,而要变为这个橘子所在的行的最大列数,同理,判断下的时候也要加上下一行的当前列是否存在,这样的话题目就复杂了很多。
在这个题中,我们把所有的烂橘子找出,腐蚀过后把之前的烂橘子扔掉,同时把新的烂橘子找出,这样一层一层的往下,这种算法是广度优先搜索(Breadth-First Search)的思想,也叫BFS,与之对应的还有一个叫深度优先搜索(Depth-First Search),即DFS,这两种算法一般用于遍历图,寻找最短路径,这里运用到了BFS的思想,先把同一层遍历完,再往下一层继续遍历。

附源代码


/*
 * @lc app=leetcode.cn id=994 lang=c
 *
 * [994] 腐烂的橘子
 */

// @lc code=start

typedef struct {
    int x;
    int y;
    int lev;
} Queue, *LPQueue;

int orangesRotting(int** grid, int gridSize, int* gridColSize){
    LPQueue q = (LPQueue)malloc(sizeof(Queue) * gridColSize[0] * gridSize);
    int front = 0, rear = 0;
    for(int i = 0; i < gridSize; ++i)
    {
        for(int j = 0; j < gridColSize[i]; ++j)
        {
            if(grid[i][j] == 2)
            {
                q[rear].lev = 0;
                q[rear].x = i;
                q[rear++].y = j;
            }
        }
    }
    int result;
    while(rear != front)
    {
        if(q[front].x-1 >= 0 && grid[q[front].x-1][q[front].y] == 1)
        {
            grid[q[front].x-1][q[front].y] = 2;
            q[rear].lev = q[front].lev+1;
            q[rear].x = q[front].x-1;
            q[rear++].y = q[front].y;
        }
        if(q[front].x+1 < gridSize && grid[q[front].x+1][q[front].y] == 1)
        {
            grid[q[front].x+1][q[front].y] = 2;
            q[rear].lev = q[front].lev+1;
            q[rear].x = q[front].x+1;
            q[rear++].y = q[front].y;
        }
        if(q[front].y-1 >= 0 && grid[q[front].x][q[front].y-1] == 1)
        {
            grid[q[front].x][q[front].y-1] = 2;
            q[rear].lev = q[front].lev+1;
            q[rear].x = q[front].x;
            q[rear++].y = q[front].y-1;
        }
        if(q[front].y+1 < gridColSize[0] && grid[q[front].x][q[front].y+1] == 1)
        {
            grid[q[front].x][q[front].y+1] = 2;
            q[rear].lev = q[front].lev+1;
            q[rear].x = q[front].x;
            q[rear++].y = q[front].y+1;
        }
        result = q[rear-1].lev;
        front++;
    }
    for(int i = 0; i < gridSize; ++i)
    {
        for(int j = 0; j < gridColSize[i]; ++j)
        {
            if(grid[i][j] == 1)
            {
                return -1;
            }
        }
    }
    return result;
}

// @lc code=end  

    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,064评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,606评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,011评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,550评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,465评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,919评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,428评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,075评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,208评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,185评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,191评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,914评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,482评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,585评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,825评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,194评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,703评论 2 339

推荐阅读更多精彩内容

  • 动态网格问题 这里的动态网格问题,指的是这样一类问题:存在一个网格盘grid,其中的各个网格存放着对应的值,并且这...
    9_SooHyun阅读 211评论 0 0
  • B1023. 组个最小数 (4.4 贪心) 思路: 先在1~9这9个数字中,确定最高位,0不能作最高位。但是确定完...
    StevenHD阅读 39评论 0 0
  • 1.Iterator接口 迭代器:逐个访问集合内的元素,这种方式叫迭代方式。foreach循环语法,对数组元素逐个...
    hhp895阅读 252评论 0 3
  • 这一篇讲的是为政有规律,也有方法和原则。 第一遍读的时候我先理解它本来的意思,第二遍的时候我能联想到所学进行知识迁...
    火箭瑶阅读 591评论 0 1
  • 前情概要 顾仲海终于想到解毒的办法,孤注一掷的想要赌一把。众人齐心协力,经过一番苦斗,终于击退了古月一伙,成功的救...
    寸草945阅读 373评论 0 3