- 飞地的数量
给出一个二维数组 A,每个单元格为 0(代表海)或 1(代表陆地)。
移动是指在陆地上从一个地方走到另一个地方(朝四个方向之一)或离开网格的边界。
返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。
示例 1:
输入:[[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
输出:3
解释:
有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。
示例 2:
输入:[[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
输出:0
解释:
所有 1 都在边界上或可以到达边界。
提示:
1 <= A.length <= 500
1 <= A[i].length <= 500
0 <= A[i][j] <= 1
所有行的大小都相同
总体思路:DFS深度优先搜索算法,比如:常用于搜索逃出迷宫的路径,即利用dfs函数疯狂找1,找完和自己联通的1周再回到numEnclaves中。
本题思路:对于处于边界上的1,疯狂找1,找到的1都可以通过边界出去
对于非边界上的1,疯狂找1如果找到边界上的1则可以出去,即如果找到边界上的1在代码中就会发生越界,则ans[1]会为True,则cnt就不会计数;疯狂找1如果最后找不到边界上的1则表示出不去,则不会发生越界,则ans[1]会一直为True,则cnt就会计数
思路:就是对逐行对每个1进行判断,然后利用dfs递归方法实现,递归的结束条件就是发生越界,即找到了边界上的1
还有一个思路:本题中并没有用。只对边界上的1进行判断,通过边界上的1找矩阵中存在的1,一直找完,能被找到的1最后肯定都能出去。最后计算剩下的1的个数就是出不去的个数
代码:
# -*- coding: cp936 -*-
class Solution(object):
def dfs(self, i , j , A , m , n , ans):
#如果越界则直接跳出函数,同时令ans[1] = True,则表示该1是在边界上,即cnt就不会加1
if i < 0 or i >= m or j < 0 or j >= n:
ans[1] = True
print "ii is 越界 %d,jj is 越界 %d"%(i,j)
return
#如果值不为1,则直接return跳出函数
if A[i][j] != 1:
return
#当值为1时,ans加1,同时该位置的1置为-1,那么怎么判断是否是可以达到边界 的1呢
ans[0] += 1
#值为1,即找到值为1的数,则置为非1
A[i][j] = -1
#1、比如边界上某个值为1,则边界的上下左右会有一个越界,即代码会
#执行第一个if,即ans[1]会为true
#然后利用dfs会找出所有可能到达的1,并且置为非1,找完才会回到numEnclaves函数中
#这时因为ans[1]始终为true,即cnt不会加1,即找到的1都可通过边界上的1出去
#2、如果边界上全为0,中间有几个1,则另其中1个1为起点,然后上下左右疯狂找其他1,
#则ans[1]会始终为False,ans[0]、cnt会不断加1,最终算出,出不去的1的总个数
#注意:回到numEnclaves函数中意味着dfs有新的起接点,并且ans[1]重新置为false
for ii, jj in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:
print "ii is取 %d,jj is取 %d"%(ii,jj)
self.dfs(ii, jj, A, m, n, ans)
print A
print ans
def numEnclaves(self, A ) :
m, n = len(A), len(A[0])
cnt = 0
for i in range(m):
for j in range(n):
if A[i][j] == 1:
print "i is%d j is %d"%(i,j)
ans = [0, False]
self.dfs(i, j, A, m, n, ans)
if not ans[1]:
cnt += ans[
return cnt
s=Solution()
print s.numEnclaves([[0,0,1,0],[0,0,1,0],[0,0,0,0],[0,0,0,0]])
备注:1、利用了ans列表,也可以申请为2个变量分别写
2、二维数组的行和列的长度,分别为len(A), len(A[0])
3、if not False:表示如果是false则执行,如果是True则不执行if里的语句