LeetCode之路:463. Island Perimeter
来源:互联网 发布:java中flag的用法 编辑:程序博客网 时间:2024/06/05 07:14
一、引言
这道题的题目信息请点击这里查看Island Perimeter。
其实我一看到这道题,我就想到了我之前做过的一个五子棋的项目。关于这个项目我还写了一篇博客,可以点击这里查看一个使用纯Win32 SDK和C语言实现的五子棋游戏。
这里让我们想想,五子棋的判胜逻辑。
五子棋五子棋,顾名思义,就是五个同色的棋子连接成了一条线,则判定胜利。那么五子棋的判胜逻辑应该怎么完成呢?
这里进行简要的总结:其实主要的核心思想就是以一个棋子为观察原点,我们以这个棋子出发,观察八个方向(包括四个斜方向)是否存在同色棋子,然后递归计数即可。
回到这道题,其实我们以一个 island 为中心,观察它附近是否存在 island,如果存在,则周长 -1 即可。
二、我的代码
这里我再来总结下思路:
1. 遍历整个 grid,找到其中所有的 island,也就是值为 1 的点
2. 以这个点为中心,检测它附近是否有 island,也就是检测它附近的四个方向的点(上下左右)是否值为 1。这里我们假想一下,其实很简单,只要有一个相邻的 island,周长就会减少 1,最后我们将每个 island 的周长计数加起来即可。
3. 将每个 island 的周长计数加起来即可。
代码如下:
class Solution {public: struct point { unsigned x; unsigned y; }; int validSideCount(const point &pt, vector<vector <int>> &grid) { int validSideCount = 0; if (pt.x == 0 || grid[pt.x - 1][pt.y] == 0) { ++validSideCount; } if (pt.x == grid.size() - 1 || grid[pt.x + 1][pt.y] == 0) { ++validSideCount; } if (pt.y == 0 || grid[pt.x][pt.y - 1] == 0) { ++validSideCount; } if (pt.y == grid[0].size() - 1 || grid[pt.x][pt.y + 1] == 0) { ++validSideCount; } return validSideCount; } int islandPerimeter(vector<vector<int>> &grid) { int islandPerimeter = 0; for (int row = 0; row < grid.size(); ++row) { for (int col = 0; col < grid[row].size(); ++col) { if (grid[row][col] == 1) { point pt = { row, col }; islandPerimeter += validSideCount(pt, grid); } } } return islandPerimeter; }};
这里,我声明了一个 point 类,方便记录当前 island 的坐标。validSideCount 函数的作用就是用来检测 island 附近是否存在值为 1 的点,计数一个 island 的周长,要获得所有 island 的周长,只需要将所有的 island 的周长计数加起来即可。
这里需要注意的是,validSideCount 函数中这四个判定,需要检测是否碰到了边(坐标不能超出 vector 的最大范围值),如果碰到了边,则不能进行递减或者递增操作了,这样会出现数组访问溢出错误。
三、同样,赏析一段别人的代码
直接上代码吧,写完自己的,总是要看看别人的代码为什么比自己的代码优美不是?
int islandPerimeter(vector<vector<int>>& grid) { int count=0, repeat=0; for(int i=0;i<grid.size();i++) { for(int j=0; j<grid[i].size();j++) { if(grid[i][j]==1) { count ++; if(i!=0 && grid[i-1][j] == 1) repeat++; if(j!=0 && grid[i][j-1] == 1) repeat++; } } } return 4*count-repeat*2; }
这段代码要点如下:
1. 利用了两个变量进行周长计数:
其中,count 用来计数 island 的个数, repeat 用来计数两个 island 相邻(两个 island 相邻必然导致两条周长的减少)的个数。
那么 count * 4 - repeat * 2
必然就是最终的周长,其中 repeat 的计算只计算了当前 island 的上方和左方的记录,因为下方和右方的损失也已经包括在相对方里面去了,这里就不用再多判断了,只需要乘以2即可。
- 我发现外国人写代码,很喜欢将很短小的代码块放到一行书写,比如这里的两个判断语句:
if(i!=0 && grid[i-1][j] == 1) repeat++;if(j!=0 && grid[i][j-1] == 1) repeat++;
要是我来写,准得写成这样:
if (i != 0 && grid[i - 1][j == 1) { repeat++;}if (j != 0 && grid[i)[j - 1] == 1) { repeat++;}
其实孰优孰劣一目了然,前者真的是一目了然,而我看似在认真的遵循着编码习惯,实则扰乱了眼球,让代码阅读者一眼看不到重点。
三、总结
总结就这么多,从这道题,又看到了一点点当初写五子棋游戏的影子;同时也看到了不一样的代码风格。
让我们的代码更加 elegant 吧!
- LeetCode之路:463. Island Perimeter
- LeetCode之Island Perimeter
- leetcode 463. Island Perimeter
- leetcode 463. Island Perimeter
- LeetCode 463. Island Perimeter
- 【LeetCode】 463. Island Perimeter
- [leetcode]463. Island Perimeter
- Leetcode-463. Island Perimeter
- Leetcode 463. Island Perimeter
- 【Leetcode】463. Island Perimeter
- LeetCode 463. Island Perimeter
- LeetCode--463. Island Perimeter
- 463. Island Perimeter [LeetCode]
- leetcode 463. Island Perimeter
- leetcode 463. Island Perimeter
- [LeetCode]463. Island Perimeter
- LeetCode | 463. Island Perimeter
- 【LeetCode】463. Island Perimeter
- Quartz动态定时器
- C++ 左值、右值、右值引用
- 自定义view(一):onMeasure
- UISlider用法和UIProgressView用法
- XML、Jaxp SAX解析、dom4j解析XML、XPath运用
- LeetCode之路:463. Island Perimeter
- json在java中的使用
- ZOJ2100-Seeding(dfs基础题)
- 哈希表入门讲解
- [CAQ7]使用单例时发现数据不一致
- 方法
- Java 集合框架
- 【java】五子棋人机对弈
- String