• 合并有交集的集合


    本文转自CSDN-合并有交集的集合

    问题

    给定一个字符串的集合,格式如:
    {{a,b,c}, {b,d},{e,f},{g},{d,h}}

    要求将其中交集不为空的集合合并,合并完成后的集合之间无交集,例如上例应输出:
    {{a,b,c,d,h},{e,f}, {g}}

    思路

    初始化一个值全为-1, 大小跟给定的字符串集合大小一样的数组(下文叫定位数组)。然后把所有字符串转换成这种形式(字符串和字符串所出现在的集合的索引) 下文叫索引数组的集合

    a	0
    b	0,1
    c	0
    d	1,4
    e	2
    f	2
    g	3
    h	4
    

    先对索引数组的集合进行排序(没有排序会影响结果), 然后循环索引数组的集合操作定位数组( 如果索引数组大小为1, 且定位数组的当前值的位置的值为-1, 则在定位数组的当前值的位置插入当前值, 如果当前值位置的值不为-1, 则不做操作;如果索引数组有多个元素, 则依次循环每个索引,找到索引数组在定位数组里面的最小值插入

    a	0				[  0, -1, -1, -1, -1] 
    c	0				[  0, -1, -1, -1, -1]
    b	0,1				[  0,  0, -1, -1, -1] 
    d	1,4				[  0,  0, -1, -1,  0]
    e	2				[  0,  0,  2, -1,  0]
    f	2				[  0,  0,  2, -1,  0]
    g	3				[  0,  0,  2,  3,  0]
    h	4				[  0,  0,  2,  3,  0]
    

    最后这个结果数组 [0, 0, 2, 3, 0] 就是我们想要的

    • 位置为 0,1,4 为一组,合并后为{a,b,c,d,h}
    • 位置 2 为一组, 即 {e,f}
    • 位置 3 为一组, 即 {g}

    scala代码实现

    def fix(): Unit = {
        val data: Array[Set[String]] = Array(
          Set("a", "b", "c"), 
          Set("b", "d" ), 
          Set("e", "f"), 
          Set("g"), 
          Set("d", "h")
    
        )
        // 初始化一个跟groupWithSrc一样大小的数组, 全为-1
        val array = List.fill[Int](data.length)(-1).toArray
        val map = mutable.HashMap[String, ArrayBuffer[Int]]()
    
        for (i <- data.indices) {
          data(i).foreach(s => {
            if (map.containsKey(s)) { // 如果已经存在
              map(s).append(i) // 在原来的基础上增加现在的索引
            } else {
              map.put(s, ArrayBuffer(i))
            }
          })
        }
    
        val values = map.values
          .toList.sortWith((a, b) => a.mkString("") < b.mkString("")) // 排序
        println(values)
    
        values.foreach(v => {
          val indexs: ArrayBuffer[Int] = v.sortWith((a, b) => a < b)
          indexs.foreach(i => {
            val arrayI = array(i)
            if (indexs.size == 1) {
              if (arrayI == -1) { // 如果index只有一个而且位置为-1则直接插入
                array(i) = i
              }
            } else { // 如果index不止一个
              val indValues = indexs.map(array(_)).filter(_ != -1)
              val min = if (indValues.isEmpty) i else indValues.min  // 找到所有索引位置最小的值, 如果没有就当前值
              if (arrayI == -1) { //如果位置为-1 则直接插入
                array(i) = min
              } else { // 如果位置已经有值, 则比对原值是否比现在值小, 插入小的
                array(i) = if (arrayI < min) arrayI else {
                  values.foreach(arr => {  // 如果有改动, 则所有包含这个索引的都需要改动
                    if (arr.contains(i)){
                      arr.foreach(ei => array(ei) = min)
                    }
                  })
                  min
                }
              }
            }
          })
        })
    
        val tmap = new mutable.HashMap[Int, ListBuffer[Int]]()
        for (i <- array.indices) {
          val e = array(i)
          if (tmap.containsKey(e)) {
            tmap(e).append(i)
          } else {
            tmap.put(e, ListBuffer(i))
          }
        }
    
        var newBuffer = new ListBuffer[Set[String]]
        tmap.values.foreach(v => {
          var set: Set[String] = Set()
          v.foreach(set ++= data(_))
          newBuffer.append(set)
        })
    
        println(newBuffer)
      }
    
  • 相关阅读:
    详解C#break ,continue, return
    c# winform 全角自动转化半角问题(C#中ImeMode的值):转载
    简短总结一下C#里跨线程更新UI(转)
    必备:常用px,pt,em换算表(转)
    C# Textbox的ImeMode取值对中文输入法的影响 (转)
    转自:C#中TextBox水印提示的简单实现
    转载:C# this.invoke()作用 多线程操作UI 理解二
    转载:C# this.Invoke()的作用与用法 理解三
    MySQL数据库----基础操作
    python之路----线程
  • 原文地址:https://www.cnblogs.com/betabear/p/11687245.html
Copyright © 2020-2023  润新知