用于对数组进行分组的成本有效算法

时间:2017-01-23 14:24:43

标签: arrays algorithm set

任何人都可以帮我解决一些有效的算法来执行以下任务:

我有一个唯一行号的文件,每行有一个整数数组。

我需要检查每一行,以查看显示在不同行中的数组的值,并将它们放在一个组中。以下是它的外观示例:

行号;数据数组[...]

L1; [1,2,3,4,5]
L2; [2,3]
L3: [8,9]
L4: [6]
L5; [7]
L6; [5,6]

根据这些输入数据,我希望算法产生结果:

N组;行数组[...]

G1; [L1,L2,L4,L6]
G2; [ L3]
G3; [ L5]

P.S原始数据集占据了数亿行,并且可以包含近百万个数组元素......时间效率是一个问题。

由于

1 个答案:

答案 0 :(得分:1)

我相信这相当于找到图表的连通组件:

  1. 顶点对应于初始行号
  2. 如果x的数组中有一个公共元素,而y的数组是
  3. ,则两个顶点x和y之间有一条边

    这可以使用disjoint set data structure有效地完成,如下所示:

    1. MakeSet(d)代表每个数据值d(在您的示例中为1,2,3,4,5,6,7,8,9)
    2. 对于包含数组A的每一行,请为每个选择i。
    3. 调用join(A[0],A[i])

      这将为每个连接的组件生成一个集合。然后,您可以通过第二次遍历行来生成输出数组:

      set output to an array of empty lists
      for each row r
          A = array for row r
          id = find(A[0])
          output[id].append(r)
      

      Python代码示例

      from collections import defaultdict
      data=[[1,2,3,4,5],
            [2,3],
            [8,9],
            [6],
            [7],
            [5,6]]
      N=max(max(A) for A in data)
      rank=[0]*(N+1)
      parent=range(N+1)
      
      def Find(x):
          """Find representative of connected component"""
          if  parent[x] != x:
              parent[x] = Find(parent[x])
          return parent[x]
      
      def Union(x,y):
          """Merge sets containing elements x and y"""
          x = Find(x)
          y = Find(y)
          if x == y:
              return
          if rank[x]<rank[y]:
              parent[x] = y
          elif rank[x]>rank[y]:
              parent[y] = x
          else:
              parent[y] = x
              rank[x] += 1
      
      # First join all data
      for row,A in enumerate(data):
          for x in A:
              Union(A[0],x)
      
      # Then place rows into sets
      D=defaultdict(list)
      for row,A in enumerate(data):
          D[Find(A[0])].append(row+1)
      
      # Then display output
      for i,L in enumerate(D.values()):
          print i+1,L
      

      运行此代码会输出输出:

      1 [3]
      2 [1, 2, 4, 6]
      3 [5]