[LeetCode] 419. Battleships in a Board 解题报告
2017-02-16 11:49
363 查看
Given an 2D board, count how many battleships are in it. The battleships are represented with
empty slots are represented with
You receive a valid board, made of only battleships or empty slots.
Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape
row, N columns) or
At least one horizontal or vertical cell separates between two battleships - there are no adjacent battleships.
Example:
In the above board there are 2 battleships.
Invalid Example:
This is an invalid board that you will not receive - as battleships will always have a cell separating between them.
Follow up:
Could you do it in one-pass, using only O(1) extra memory and without modifying the value of the board?
这个题和前面某一个类似,求那个独立岛屿的数量。我看了以后,感觉和上一题417的思路特别像。(我看了网友的解答以后,发现自己的方法蠢酷了,又臭又长,不感兴趣的朋友,请直接跳到方法二)
方法一:
BFS搜索,和上面一题一样的,从左上角开始进行BFS搜索。使用循环和queue,boolean[][],搜索没有ship的格子“.”,然后把这个格子放到queue中,对应位置标记true,取出这个格子,继续循环,直到queue为空。
但是,一旦发现有ship的格子“X”,总和++,然后跳转到另一个函数,对这个格子四个方向的所有“X”格子进行搜索,这时候同样有另一个queue和循环,保证将这一个ship的所有格子都搜索到,并对应位置标记为true。(因为如果不一次性把当前ship对应的所有x找到,那么在后面的搜索中,可能会搜索到这个x,那就不知道这个x对应的ship到底有没有被搜索到。)
最后,返回总和即可。
由于BFS的时候,对于一个格子,搜索的是四个方向的,因此复杂度大约是O(4N),这个方法效率比较差,只打败了1.03%,代码的重用性也很差(我自己想的),不推荐。代码如下:
方法二:
这个方法代码量也少,原理也简单,网友还是机制。
它利用了这个题目的特性,根据题意,任意两个ships都是隔开的;也就是说,不可能存在一个ship,四面相邻另一个ship;再换句话说,由于所有的ship不是横着就是竖着的,所有任意一个ship的左上角第一个格子的上面和左边必然相邻的不是ship,我们只用数一数这样的格子有几个,就知道有几个ship了。
另外,这个方法需要注意的是:在当前格子位于边缘的时候,左边和上面的格子index值为-1,如果这时候再直接取值的话,会出现数组超界的错误。
这个方法大概的复杂度应该是O(2N),代码如下:
'X's,
empty slots are represented with
'.'s. You may assume the following rules:
You receive a valid board, made of only battleships or empty slots.
Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape
1xN(1
row, N columns) or
Nx1(N rows, 1 column), where N can be of any size.
At least one horizontal or vertical cell separates between two battleships - there are no adjacent battleships.
Example:
X..X ...X ...X
In the above board there are 2 battleships.
Invalid Example:
...X XXXX ...X
This is an invalid board that you will not receive - as battleships will always have a cell separating between them.
Follow up:
Could you do it in one-pass, using only O(1) extra memory and without modifying the value of the board?
这个题和前面某一个类似,求那个独立岛屿的数量。我看了以后,感觉和上一题417的思路特别像。(我看了网友的解答以后,发现自己的方法蠢酷了,又臭又长,不感兴趣的朋友,请直接跳到方法二)
方法一:
BFS搜索,和上面一题一样的,从左上角开始进行BFS搜索。使用循环和queue,boolean[][],搜索没有ship的格子“.”,然后把这个格子放到queue中,对应位置标记true,取出这个格子,继续循环,直到queue为空。
但是,一旦发现有ship的格子“X”,总和++,然后跳转到另一个函数,对这个格子四个方向的所有“X”格子进行搜索,这时候同样有另一个queue和循环,保证将这一个ship的所有格子都搜索到,并对应位置标记为true。(因为如果不一次性把当前ship对应的所有x找到,那么在后面的搜索中,可能会搜索到这个x,那就不知道这个x对应的ship到底有没有被搜索到。)
最后,返回总和即可。
由于BFS的时候,对于一个格子,搜索的是四个方向的,因此复杂度大约是O(4N),这个方法效率比较差,只打败了1.03%,代码的重用性也很差(我自己想的),不推荐。代码如下:
public class Solution { char[][] board; int nHeight; int nWidth; boolean[][] bExpl; int nTotal; Queue<int[]> queCommon; public int countBattleships(char[][] board) { if (board.length == 0||board==null || board[0].length==0) { return 0; } this.board = board; nHeight = board.length; nWidth = board[0].length; bExpl = new boolean[nHeight][nWidth]; queCommon = new LinkedList<int[]>(); // init bExpl[0][0] = true; if (board[0][0] == '.') { queCommon.add(new int[] { 0, 0 }); } else { nTotal++; findShip(new int[] { 0, 0 }); } //explore the common point while (queCommon.size() > 0) { int[] nArrCur = queCommon.poll(); // judge the current grid x or . explore(nArrCur, queCommon); } return nTotal; } private boolean isBeyond(int x, int y) { return x >= 0 && y >= 0 && x < nHeight && y < nWidth ? true : false; } private void explore(int[] n, Queue<int[]> q) { int x = n[0]; int y = n[1]; if (isBeyond(x, y - 1)) { tagNewPoint(x, y - 1, q); } if (isBeyond(x, y + 1)) { tagNewPoint(x, y + 1, q); } if (isBeyond(x - 1, y)) { tagNewPoint(x - 1, y, q); } if (isBeyond(x + 1, y)) { tagNewPoint(x + 1, y, q); } } private void exploreShip(int[] n, Queue<int[]> q) { int x = n[0]; int y = n[1]; if (isBeyond(x, y - 1)) { tagNewShip(x, y - 1, q); } if (isBeyond(x, y + 1)) { tagNewShip(x, y + 1, q); } if (isBeyond(x - 1, y)) { tagNewShip(x - 1, y, q); } if (isBeyond(x + 1, y)) { tagNewShip(x + 1, y, q); } } private void findShip(int[] n) { Queue<int[]> queShip = new LinkedList<int[]>(); queShip.add(n); while (queShip.size() > 0) { int[] nArrCur = queShip.poll(); // find all nearby ship exploreShip(nArrCur, queShip); } } private void tagNewPoint(int x, int y, Queue<int[]> q) { if (bExpl[x][y] == false) { bExpl[x][y] = true; int[] nn = { x, y }; if (board[x][y] == '.') { q.add(nn); } else { nTotal++; //when meets the ship, and find the whole ship once findShip(nn); } } } private void tagNewShip(int x, int y, Queue<int[]> q) { if (bExpl[x][y] == false) { bExpl[x][y] = true; int[] nn = { x, y }; if (board[x][y] == 'X') { q.add(nn); } else { queCommon.add(nn); } } } }
方法二:
这个方法代码量也少,原理也简单,网友还是机制。
它利用了这个题目的特性,根据题意,任意两个ships都是隔开的;也就是说,不可能存在一个ship,四面相邻另一个ship;再换句话说,由于所有的ship不是横着就是竖着的,所有任意一个ship的左上角第一个格子的上面和左边必然相邻的不是ship,我们只用数一数这样的格子有几个,就知道有几个ship了。
另外,这个方法需要注意的是:在当前格子位于边缘的时候,左边和上面的格子index值为-1,如果这时候再直接取值的话,会出现数组超界的错误。
这个方法大概的复杂度应该是O(2N),代码如下:
public class Solution { public int countBattleships(char[][] board) { if (board == null) { return 0; } int nTotal = 0; for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (board[i][j] == 'X') { boolean bI = i == 0 ? true : false; boolean bJ = j == 0 ? true : false; if (!bI) { bI = board[i - 1][j] == '.' ? true : false; } if (!bJ) { bJ = board[i][j - 1] == '.' ? true : false; } if (bI && bJ) { nTotal++; } } } } return nTotal; } }
相关文章推荐
- 【LeetCode】419. Battleships in a Board 解题报告(Python)
- Leetcode 419. Battleships in a Board 战舰数量 解题报告
- LeetCode 419. Battleships in a Board 解题报告
- [Leetcode] 419. Battleships in a Board 解题报告
- 【LeetCode】419.Battleships in a Board(Medium)解题报告
- 【LeetCode】Substring with Concatenation of All Words 解题报告
- [leetcode] 216. Combination Sum III 解题报告
- [Leetcode] 60. Permutation Sequence 解题报告
- [LeetCode]Remove Duplicates from Sorted List解题报告
- Leetcode 解题报告
- LeetCode 387. First Unique Character in a String 解题报告
- Leetcode Add Two Numbers解题报告
- [leetcode] 349. Intersection of Two Arrays 解题报告
- 【LeetCode】57.Insert Interval(Medium)解题报告
- LeetCode解题报告--Remove Nth Node From End of List
- leetcode解题报告14. Longest Common Prefix
- 【LeetCode】189.Rotate Array(Easy)解题报告
- [Leetcode] 564. Find the Closest Palindrome 解题报告
- [leetcode] 34. Search for a Range 解题报告
- 【LeetCode】Group Anagrams 解题报告(Python & Java)