本文转自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)
}