zoukankan      html  css  js  c++  java
  • Number of Islands II

    Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). Originally, the 2D matrix is all 0 which means there is only sea in the matrix. The list pair has k operator and each operator has two integer A[i].x, A[i].y means that you can change the grid matrix[A[i].x][A[i].y] from sea to island. Return how many island are there in the matrix after each operator.

    先给出二维矩阵的行列值,之后再给出一系列操作数目,每个操作是在一个位置插入岛屿。和Number of Islands这种先给出全部岛屿布图不一样,这种情景下更适合使用并查集,因为预先给出岛屿分布,还是无法确定操作的数目,需要扫描二维矩阵,判断为1的地方进行操作。反而使用DFS更方便一些。这题每次加入一个一个岛屿相当于新加入一个集合。之后判断这个新加岛屿上下左右是否有岛屿,如果存在的话,进行集合的合并,把当前岛屿加入,并减少岛屿的个数。

    # Definition for a point.
    # class Point:
    #     def __init__(self, a=0, b=0):
    #         self.x = a
    #         self.y = b
    
    class Solution:
        # @param {int} n an integer
        # @param {int} m an integer
        # @param {Pint[]} operators an array of point
        # @return {int[]} an integer array
        def numIslands2(self, n, m, operators):
            if not m or not n or not operators:
                return []
            UF = UnionFind()
            res = []
            for p  in  map(lambda a: (a.x, a.y), operators):
                UF.add(p)
                for dx in (1, 0), (0, 1), (-1, 0), (0, -1):
                    q =  (dx[0] + p[0], dx[1]+p[1])
                    if q in UF.id:
                        UF.union(p,q)
                res += [UF.count]
            return res
                        
    class UnionFind(object):
        def __init__(self):
            self.id = {} #object
            self.sz = {} #object'weight, size here.
            self.count = 0
            
        def add(self, p):
            self.id[p] = p
            self.sz[p] = 1
            self.count += 1
            
        def find(self, i):
            while i!= self.id[i]:
                self.id[i] = self.id[self.id[i]] #路径压缩
                i = self.id[i]
            return i
    
        def union(self, p, q):
            i = self.find(p)
            j = self.find(q)
            if i == j:
                return
            if self.sz[i] > self.sz[j]: #union is only operated on heads按秩合并
                i, j = j, i
            self.id[i] = j
            self.sz[i] += self.sz[j]
            self.count -= 1

    以上操作的最多合并次数为4k次,object k个。所以时间复杂度为O((4k+k)log*k).log*为迭代次数,不超过5,所以时间复杂度为O(k)大小。空间复杂度为两个dict(权重和father),O(k)大小。由于key值是tuple,空间消耗非常大,所以这种解法在lintcode上MLE. 可以每次将二维坐标转化为一维坐标来做键值。 

    Leetcode版本解法: 二维坐标转化为一维数字的表达,一定要注意乘的是列数不是行数!!

    class Solution(object):
        def numIslands2(self, m, n, positions):
            """
            :type m: int
            :type n: int
            :type positions: List[List[int]]
            :rtype: List[int]
            """
            #union find method
            #union find init function, find function, union function,add function the basic architecture is hashmap.
            #extra space-saving method, turn the 2D coordinates into 1D, multiply the number of column not row
            res = []
            delta = [1,0,-1,0,1]
            UF = UnionFind()
            for a in positions:
                UF.add(a[0]*n + a[1])
                for i in xrange(4):
                    x = a[0] + delta[i]
                    y = a[1] + delta[i+1]
                    p = x*n+y
                    if 0 <= x < m and 0 <= y < n and p in  UF.root:
                        UF.union(a[0]*n + a[1], p)
                res.append(UF.cnt)
            return res
    class UnionFind(object):
        def __init__(self):
            self.root = {}
            self.sz = {}
            self.cnt = 0
        def add(self, x):
            self.root[x] = x
            self.sz[x] = 1
            self.cnt += 1
        def find(self, x): #find the root of a node
            while x!= self.root[x]:
                self.root[x] = self.root[self.root[x]]
                x = self.root[x]
            return x
        def union(self, x, y): #attention, just union the big brother, link smaller union to the larger one
            i = self.find(x)
            j = self.find(y)
            if i != j: #not in the same union
                if self.sz[i] > self.sz[j]:
                    self.root[j] = i
                    self.sz[i] += self.sz[j]
                else:
                    self.root[i] = j
                    self.sz[j] += self.sz[i]
                self.cnt -= 1
                
            
  • 相关阅读:
    POJ 2533 Longest Ordered Subsequence(裸LIS)
    HDU 1159 Common Subsequence(裸LCS)
    HDU 1160(两个值的LIS,需dfs输出路径)
    HDU 1260 Tickets (普通dp)
    HDU 2859 Phalanx(对称矩阵 经典dp样例)
    2018年暑假ACM个人训练题7 题解报告
    HDU 1060 Leftmost Digit(求N^N的第一位数字 log10的巧妙使用)
    HDU 1071 The area(求三个点确定的抛物线的面积,其中一个点是顶点)
    HDU 1077 Catching Fish(用单位圆尽可能围住多的点)
    HDU 1099 Lottery (求数学期望)
  • 原文地址:https://www.cnblogs.com/sherylwang/p/5576007.html
Copyright © 2011-2022 走看看