```fun mergeKLists(lists: Array<ListNode?>):...
# announcements
w
Copy code
fun mergeKLists(lists: Array<ListNode?>): ListNode? {
        var holder: List<ListNode?> = arrayListOf()
        while (true) {
            val bulk = lists.withIndex().minBy { (_, value) -> value?.`val` ?: Int.MAX_VALUE }
            val index = bulk?.component1(); val lowest = bulk?.component2() ?: break
            holder += lowest
            lists[index!!] = lists[index]?.next
        }
        for (index in 1 until holder.size) holder[index-1]?.next = holder[index]
        return if (holder.isNotEmpty()) holder[0] else null
    }
c
There's #C1H43FDRB channel, #C0922A726 is more for specific questions/discussions.
i
I wonder when do you expect your
while
loop to terminate?
w
@Czar got it
@ilya.gorbunov when
lowest
becomes
null
. it works correctly but perhaps not the best in terms of clarity?
i
minBy
returns
null
when there are no elements in
lists
, I don't see how
lists
array can become empty.
Hmm, now I see that the second component can be null itself and it will terminate the loop. I suggest to rewrite it this way:
Copy code
val (index, lowest) = lists.withIndex().minBy { ... } ?: break
if (lowest == null) break
// here both index and lowest are not null
Each time you add value to holder list as
holder += lowest
that list is recreated, because it is declared as read-only and var. If you declare it as
val holder: MutableList<ListNode?>
the values will be added to the existing mutable list.
if (holder.isNotEmpty()) holder[0] else null
can be replaced with
holder.firstOrNull()
w
@ilyagorbunov Thanks a lot for all the suggestions!
Copy code
fun mergeKLists(lists: Array<ListNode?>): ListNode? {
        val holder: MutableList<ListNode?> = arrayListOf()
        while (true) {
            val (index, lowest) = lists.withIndex().minBy { (_, value) -> value?.`val` ?: Int.MAX_VALUE }  ?: break
            if (lowest == null) break
            holder += lowest
            lists[index] = lists[index]?.next
        }
        for (index in 1 until holder.size) holder[index-1]?.next = holder[index]
        return holder.firstOrNull()
    }
Looking much cleaner and more readable now
i
I also think it's not a good idea to take
withIndex
in a tight loop, because it will create a lot of
IndexedValue
wrappers (number of lists x number of elements) I suppose. Instead you can find the index of minimum element as following:
Copy code
val indices = lists.indices
while(true) {
     val indexOfMin = indices.minBy { lists[it]?.val ?: Int.MAX_VALUE } ?: break
     val lowest = lists[indexOfMin] ?: break
w
indices.minBy { lists[it]?.val ?: Int.MAX_VALUE } ?: break
this is quite interesting
i was under the impression that sorting condition for minBy must come from the collection minBy was called on
cool stuff