zoukankan      html  css  js  c++  java
  • (原)Max Area of Island(即连通域标记)

    转载请注明出处:

    https://www.cnblogs.com/darkknightzh/p/10493114.html

    1. 问题

    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.

    2 解决方法

    这题就是连通域标记,用matlab的[~,num]=bwlabel(data,4)直接可以得到对于example 1,num=6。

    纯粹编程的话,有想到了两种方法:

    1 深度优先遍历,对于某个为1的点,遍历其周围的4个点,直到到达边界或者为0。

    2 得到值为1的坐标,然后计算|x1-y1|+|x2-y2|=1的坐标,并把这些坐标连起来,就是一个区域了,比如点a连接点b,点b连接点d,点d连接点c,则a,b,c,d这四个点是连起来的一个区域,串起来即可。

    对于第一种方法,写起来简单一些。对于第二种方法,不清楚有没有简单的写法,本文只能使用最笨的方法,验证了两个example都是正确的,没有进一步验证其他数据。

    3 Matlab代码

    Matlab代码如下(使用深度优先遍历):

    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

    4. python代码

    Python代码使用第二种方法,将连接的点串起来(不知道有没有好的解决方法,下面的代码比较笨,另外,代码中method1和method2都可以,method1计算量大一些,method2计算量小一些,但是不确定method2是不是完全正确。。。)

     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)
  • 相关阅读:
    SDWebImage缓存下载图片
    NSMutableUrlRequest自定义封装网络请求
    第152题:乘积最大子序列
    第142题:环形链表II
    第17题:电话号码的组合
    第129题:求根到叶子节点数字之和
    第125题:验证回文串
    第122题:买卖股票的最佳时机II
    第121题:买卖股票的最佳时机
    第120题:三角形最小路径和
  • 原文地址:https://www.cnblogs.com/darkknightzh/p/10493114.html
Copyright © 2011-2022 走看看