轉載請註明出處:html
http://www.javashuo.com/article/p-tvzizqzf-bu.htmlpython
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water. Find the maximum area of an island in the given 2D array. (If there is no island, the maximum area is 0.) Example 1: [0,0,1,0,0,0,0,1,0,0,0,0,0], [0,0,0,0,0,0,0,1,1,1,0,0,0], [0,1,1,0,1,0,0,0,0,0,0,0,0], [0,1,0,0,1,1,0,0,1,0,1,0,0], [0,1,0,0,1,1,0,0,1,1,1,0,0], [0,0,0,0,0,0,0,0,0,0,1,0,0], [0,0,0,0,0,0,0,1,1,1,0,0,0], [0,0,0,0,0,0,0,1,1,0,0,0,0]] Given the above grid, return 6. Note the answer is not 11, because the island must be connected 4-directionally. Example 2: [[0,0,0,0,0,0,0,0]] Given the above grid, return 0.
這題就是連通域標記,用matlab的[~,num]=bwlabel(data,4)直接能夠獲得對於example 1,num=6。編程
純粹編程的話,有想到了兩種方法:app
1 深度優先遍歷,對於某個爲1的點,遍歷其周圍的4個點,直到到達邊界或者爲0。spa
2 獲得值爲1的座標,而後計算|x1-y1|+|x2-y2|=1的座標,並把這些座標連起來,就是一個區域了,好比點a鏈接點b,點b鏈接點d,點d鏈接點c,則a,b,c,d這四個點是連起來的一個區域,串起來便可。code
對於第一種方法,寫起來簡單一些。對於第二種方法,不清楚有沒有簡單的寫法,本文只能使用最笨的方法,驗證了兩個example都是正確的,沒有進一步驗證其餘數據。htm
Matlab代碼以下(使用深度優先遍歷):blog
function testIsland() clc clear all close all % data = [[0,0,1,0,0,0,0,1,0,0,0,0,0], % [0,0,0,0,0,0,0,1,1,1,0,0,0], % [0,1,1,0,1,0,0,0,0,0,0,0,0], % [0,1,0,0,1,1,0,0,1,0,1,0,0], % [0,1,0,0,1,1,0,0,1,1,1,0,0], % [0,0,0,0,0,0,0,0,0,0,1,0,0], % [0,0,0,0,0,0,0,1,1,1,0,0,0], % [0,0,0,0,0,0,0,1,1,0,0,0,0]]; data = [[0,0,0,0,0,0,0,0]]; [island_num, ~] = island(data); end function [island_num, label] = island(data) island_num = 0; label = data; for i=1:size(label, 1) for j=1:size(label, 2) if label(i, j)==1 island_num = island_num +1; label = recurseFinding(label, i, j, island_num); end end end end function data = recurseFinding(data, i, j, island_num) if i>0 && i<=size(data, 1) && j>0 && j<=size(data, 2) && data(i, j)==1 data(i, j) = island_num; data = recurseFinding(data, i-1, j, island_num); data = recurseFinding(data, i+1, j, island_num); data = recurseFinding(data, i, j-1, island_num); data = recurseFinding(data, i, j+1, island_num); end end
Python代碼使用第二種方法,將鏈接的點串起來(不知道有沒有好的解決方法,下面的代碼比較笨,另外,代碼中method1和method2均可以,method1計算量大一些,method2計算量小一些,可是不肯定method2是否是徹底正確。。。)get
1 import numpy as np 2 import copy 3 4 def recurseFinding(dict_in, key, islands): 5 ret_list = [] 6 for val in dict_in[key]: 7 ret_list.append(val) 8 if dict_in.__contains__(val) and not islands.__contains__(val): 9 ret_list = list(set(ret_list + [l for l in recurseFinding(dict_in, val, islands)])) 10 return ret_list 11 12 def island_num(data): 13 loc_xy = [[i, j] for i in range(data.shape[0]) for j in range(data.shape[1]) if data[i,j]>0] # 獲得不爲0的全部座標(x,y) 14 loc_idx_dict = {i:loc_xy[i] for i in range(len(loc_xy))} # 給座標編號,方便後面使用 15 loc_key = sorted(set(loc_idx_dict.keys())) 16 17 pairs_dict = {} 18 for i in range(len(loc_key)-1): 19 for j in range(i+1, len(loc_key)): 20 if abs(loc_idx_dict[loc_key[i]][0] - loc_idx_dict[loc_key[j]][0]) + abs(loc_idx_dict[loc_key[i]][1] - loc_idx_dict[loc_key[j]][1]) == 1: 21 if not pairs_dict.__contains__(loc_key[i]): 22 pairs_dict[loc_key[i]] = [] 23 pairs_dict[loc_key[i]].append(loc_key[j]) 24 25 islands_dict = {} 26 for k, v in pairs_dict.items(): 27 if k in [j for i in islands_dict.values() for j in i]: 28 continue 29 if not islands_dict.__contains__(k): 30 islands_dict[k] = copy.deepcopy(pairs_dict[k]) 31 islands_dict[k] = recurseFinding(pairs_dict, k, islands_dict) 32 33 ############### method1 34 # islands_keys = sorted(set(islands_dict.keys())) # 可能出現11:[18,19], 12:[18]的狀況,須要將12合併到11中,繼續遍歷一下,此處比較麻煩 35 # for i in range(len(islands_keys)-1): 36 # for j in range(i+1, len(islands_keys)): 37 # flags= False 38 # for v2 in islands_dict[islands_keys[j]]: 39 # if v2 in islands_dict[islands_keys[i]]: 40 # islands_dict[islands_keys[i]].append(islands_keys[j]) 41 # flags = True 42 # if flags: 43 # islands_dict[islands_keys[j]] = [] # 此處沒法刪除12的key,不然程序崩潰,於是只能置空,後面刪除 44 45 ############### method1 end 46 47 ############### method2 48 reverse_pairs = {} # 獲得反轉的對應關係,若是出現11:[18,19], 12:[18]的狀況,則反轉後的鍵18對應2個值 49 for k,v in islands_dict.items(): 50 for v0 in v: 51 if not reverse_pairs.__contains__(v0): 52 reverse_pairs[v0] = [] 53 reverse_pairs[v0].append(k) 54 55 delete_key = [] # 理論上比method1計算量少,可是不肯定是否徹底正確。。。 56 for k,v in reverse_pairs.items(): 57 if len(v) > 1: 58 for i in range(1, len(v)): 59 if v[i] not in islands_dict[v[0]]: 60 islands_dict[v[0]].append(v[i]) 61 if v[i] not in delete_key: 62 delete_key.append(v[i]) 63 64 for k in delete_key: # 刪除對應的key 65 del islands_dict[k] 66 ############### method2 end 67 68 islands_dict = {k:set(v) for k, v in islands_dict.items() if len(v) > 0} 69 70 pairs_keys = set(pairs_dict.keys()) 71 pairs_vals = set([v0 for v in pairs_dict.values() for v0 in v]) 72 alone_loc = set(loc_key) - (pairs_keys | pairs_vals) #因爲優先級,後面須要加括號 73 islands_dict.update({i:[] for i in alone_loc}) # 將單獨的位置合併到islands_dict中 74 75 return len(islands_dict) # 經過islands_dict及loc_idx_dict能夠找到對應的座標,此處省略 76 77 78 # data=np.array([ [0,0,1,0,0,0,0,1,0,0,0,0,0], 79 # [0,0,0,0,0,0,0,1,1,1,0,0,0], 80 # [0,1,1,0,1,0,0,0,0,0,0,0,0], 81 # [0,1,0,0,1,1,0,0,1,0,1,0,0], 82 # [0,1,0,0,1,1,0,0,1,1,1,0,0], 83 # [0,0,0,0,0,0,0,0,0,0,1,0,0], 84 # [0,0,0,0,0,0,0,1,1,1,0,0,0], 85 # [0,0,0,0,0,0,0,1,1,0,0,0,0]]) 86 87 data=np.array([[0,0,0,0,0,0,0,0]]) 88 89 num = island_num(data) 90 print(num)