如何合并包含递归公共属性的列表

时间:2018-05-09 01:37:39

标签: algorithm scala functional-programming

输入为List(1,2), List(3,4), List(1000), List(5,6), List(100, 1,3), List(99, 4, 5)

预期输出为:List(1,2,3,4,5,6,99,100), List(1000)

我尝试使用foldLeft,但我发现一个循环O(n)会丢失一些元素。我想知道Scala集合api或方法是否可以用来解决这个难题?此外,如果可能的话,我更愿意更具功能性。

def merge(lists: List[List[Int]]): List[List[Int]] = {
   ???
}

提前致谢。

3 个答案:

答案 0 :(得分:1)

您可以尝试此功能。它也适用于巨大的列表

def merge(input: List[List[Int]]): List[List[Int]] = {

  val sets: Set[Set[Int]] = input.map(_.toSet).toSet

  def hasIntersect(set: Set[Int]): Boolean =
    sets.count(set.intersect(_).nonEmpty) > 1

  val (merged, rejected) = sets partition hasIntersect
  List(merged.flatten, rejected.flatten).map(_.toList.sorted)
}

merge(List(List(1, 2), List(3, 4), List(1000), List(5, 6), List(100, 1, 3), List(99, 4, 5)))

您将以

格式获得结果
res0: List[List[Int]] = List(List(1, 2, 3, 4, 5, 6, 99, 100), List(1000))

如果您有任何疑问,请告诉我。我很乐意澄清它们。

答案 1 :(得分:1)

您需要的只是filtertoSetsorted函数调用为

def merge(lists: List[List[Int]]): List[List[Int]] = {
  val flattenedList = lists.flatten
  val repeatedList = lists.filter(list => list.map(x => flattenedList.count(_ == x) > 1).contains(true))
  val notRepeatedList = lists.diff(repeatedList)
  List(repeatedList.flatten.toSet.toList.sorted) ++ notRepeatedList
}

然后将merge函数调用为

val lists = List(List(1,2), List(3,4), List(1000), List(5,6), List(100, 1,3), List(99, 4, 5))

println(merge(lists))

会给你

List(List(1, 2, 3, 4, 5, 6, 99, 100), List(1000))

答案 2 :(得分:1)

以下是一个递归解决方案供您参考:

def merge(a:List[List[Int]]):List[List[Int]] = {
  a match {
    case Nil => Nil
    case h::l =>
    l.partition(_.intersect(h)!=Nil) match {
      case (Nil, _) =>
      //No intersect, just merge the rest and add this one
      h::merge(l)
      case (intersects, others) =>
      //It has intersects, merge them to one list and continue merging
      merge((h::intersects).flatten.distinct::others)
    }
  }
}
res9: List[List[Int]] = List(List(1, 2, 100, 3, 4, 99, 5, 6), List(1000))