Ungrouping of values into multiple lists
Played a bit with it... how do you like the following?

fun &lt;T&gt; ungroupDuplicateValues(values: List&lt;T&gt;): List&lt;List&lt;T&gt;&gt; {
  val countPerValue = values.groupingBy { it }.eachCount()
  val maxCount = countPerValue.map { it.value }.max() ?: 0
  return (1..maxCount).map { index -&gt;
    countPerValue.filterValues { it &gt;= index }
        .map { it.key }
  }
}


Complexity (in regards to O-notation) should be similar to yours...

Or the following variant using tailrec:

fun &lt;T&gt; ungroupDuplicateValues(values: List&lt;T&gt;) = ungroupDuplicateValues(values.toMutableList())

private tailrec fun &lt;T&gt; ungroupDuplicateValues(remainingValues : MutableList&lt;T&gt;, newValues : MutableList&lt;List&lt;T&gt;&gt; = mutableListOf()) : List&lt;List&lt;T&gt;&gt; {
  val values = remainingValues.distinct()
  newValues.add(values)
  values.forEach { remainingValues.remove(it) }
  return if (remainingValues.isEmpty()) newValues
         else ungroupDuplicateValues(remainingValues, newValues)
}


But don't ask me about the O-notation here. tailrec should be optimized, but as I still use a forEach { remove } it will probably still be O(n²).

If you rather prefer a direct assigned function (of the first shown solution), maybe the following is also ok for you:

fun &lt;T&gt; ungroupDuplicateValues(values: List&lt;T&gt;) =
  values.groupingBy { it }.eachCount().let { countPerValue -&gt;
    (countPerValue.map { it.value }.max() ?: 0).let { maxCount -&gt;
      (1..maxCount).map { index -&gt;
        countPerValue.filterValues { it &gt;= index }
            .map { it.key }
      }
    }
  }