LeetCode - 463. Island Perimeter

题目链接:463. Island Perimeter


题目大意:这里给你一个map(实际上是一个二维数组),这个二维数组中的0代表了水,1代表了岛(也就是陆地)。这些二位数组组成的网格是水平或垂直连接的(没有对角线)。这个网格中只包含了一块岛,其余的都是水,并且岛上没有湖泊。一个格子是一个边长为1的正方形,这个网格整体是个矩形,并且长和宽都不超过100,求出岛的周长。


[[0,1,0,0],
 [1,1,1,0],
 [0,1,0,0],
 [1,1,0,0]]

island
题解:
结合上面的二维数组和对应的岛屿图来解释一下。
这个题做起来重点关注的就是两块相连的陆地的那条边不需要计算,另外位于图片边缘的陆地的边需要计算在内。其余的就没什么了。


这里先说一下我的解法:
这个解法就是最普通的解法,一点点去判断,虽然代码写的不够简洁,优雅,但是效果却很不错,跑完后超出60%的人。

def islandPerimeter(self, grid):
    x = len(grid)
    y = len(grid[0])

    perimeter = 0

    for i in range(x):
        for j in range(y):
            if grid[i][j] == 1:
                if i-1 < 0 or i+1 >= x:
                    perimeter += 1
                if j-1 < 0 or j+1 >= y:
                    perimeter += 1
                if i-1 > -1 and grid[i-1][j] == 0:
                    perimeter += 1
                if i+1 < x and grid[i+1][j] == 0:
                    perimeter += 1
                if j-1 > -1 and grid[i][j-1] == 0:
                    perimeter += 1
                if j+1 < y and grid[i][j+1] == 0:
                    perimeter += 1
    return perimeter

第二种解法:
这种解法就是上面写法的简化版,但是不知道为什么效率出奇的低,大概是使用了特殊的数据结构吧

class Solution(object):
    def islandPerimeter(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if not grid:
            return 0

        def sum_adjacent(i, j):
            adjacent = (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1),
            res = 0
            for x, y in adjacent:
                if x < 0 or y < 0 or x == len(grid) or y == len(grid[0]) or grid[x][y] == 0:
                    res += 1
            return res

        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 1:
                    count += sum_adjacent(i, j)
        return count

以上是那个哥们的原始解法,只超过5%的人,看的我目瞪口呆,明明写的很不错,所以我略微改进了一下。

class Solution(object):
    def islandPerimeter(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if not grid:
            return 0

        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 1:
                    adjacent = (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1),
                for x, y in adjacent:
                    if x < 0 or y < 0 or x == len(grid) or y == len(grid[0]) or grid[x][y] == 0:
                        count += 1
        return count

这样改动后,超过12%的人,哎,还是太慢了。


最后上个最优解(个人认为),这位大神在我目前做的几道题下都有碰到,真的非常非常厉害,特别擅长一行代码解决问题,没错这个题也可以一行代码搞定。

def islandPerimeter(self, grid):
    return sum(sum(map(operator.ne, [0] + row, row + [0]))
               for row in grid + map(list, zip(*grid)))

这里解释一下:大神的解释是这道题的本质就是求解两个相邻位置上的值不同的个数(包括水平和垂直),求解相邻位置上的值是否不同的方式是对每一行以及每一列,在行(列)的前面加一个[0]作为数组A,在行(列)的后面加一个[0]作为数组B,比较AB数组中相同位置上的值不同的个数,这就是在这一行中岛的周长的长度,以此类推,算出所有行列的值,就可以得到岛的面积了。
接下来解释一下代码中的一些函数:首先说一下zip函数,这个zip函数大概的意思就是接受一系列的序列,并将这些序列以矩阵转置的操作方式处理,如果序列长度不一,按照最短的处理。可以看看这篇博客加深理解python zip函数讲解,下一个是operator.ne,这个函数是原来在python中是内置函数,但在python3中,需要通过导入来使用import operator,这里的ne的意思是判断两个数是否不同。

import operator

print(operator.ne(5, 3))
True
print(operator.ne(3, 3))
False

关于operator函数的用法,看这里

最后的最后还有一个事需要注意,似乎在python3中不能直接写grid + map(list, zip(*grid)),我自己在本地这样写的时候会报错,如果你也是用的python3,并且上述写法也会报错的话,可以试着这样写grid + [x for x in map(list, zip(*grid))],看起来麻烦了一些,我个人对于python的理解非常浅薄,如果大神知道更好的写法,望告知。
这次的题目让我对python语言的简洁性有了更深刻的认知,因为上述的最后一种解法所用的时间竟然也能超过60%的人,这一点真的是没有想到。自己需要学习的东西还是有很多啊。

以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值