Problem overview
The function moveToFront gets a to-do list items (a MutableList<String>) and an index. It takes the item at index out of its place and puts it at index 0. The other items keep their order. The index is always valid, from 0 to the size minus 1, and the same word may appear more than once.
For ["wash", "shop", "cook", "read"] and index = 2, "cook" moves to the front and "wash" and "shop" shift one place to the right. For ["tea", "coffee"] and index = 0 nothing changes.
Approach
This is a remove followed by an insert. removeAt(index) takes the item out and returns it, and the items behind it close the gap. add(0, item) then inserts it at the front and shifts everything else one place to the right. The items that were in front of the removed one end up one place further right, and the ones behind it end up where they were, so every other item keeps its relative order.
Step by step
- Remove and keep.
items.removeAt(index)returns the removed item; store it in avalnameditem. - Insert at the front.
items.add(0, item), with the index first. Whenindexis 0, the item goes back where it was. - Return
items.
The solution in Kotlin
class Solution {
fun moveToFront(items: MutableList<String>, index: Int): MutableList<String> {
val item = items.removeAt(index)
items.add(0, item)
return items
}
}
On the three examples it gives (values separated by spaces):
cook wash shop read
tea coffee
call call pay walk
The function changes items itself and returns that same list, so the caller's list is moved too. In the third example the two "call" words are equal, so it matters that removeAt works by position: it removes the one at index 2, not the first one it finds.
What the list looks like at each step
Take ["wash", "shop", "cook", "read"] with index = 2:
| Step | Code | item | items |
|---|---|---|---|
| start | [wash, shop, cook, read] | ||
| 1 | removeAt(2) | cook | [wash, shop, read] |
| 2 | add(0, item) | cook | [cook, wash, shop, read] |
With ["tea", "coffee"] and index = 0, the list is [coffee] after the removal and [tea, coffee] again after the insert.
Another way
The two steps can be written as one line, because removeAt returns the item that add needs:
items.add(0, items.removeAt(index))
It does the same thing and gives the same results on all three examples. The version with a named item is easier to read and to step through, so it is the one the lesson uses.
Edge cases and common mistakes
- Using
removeinstead ofremoveAt.removelooks for a value. On a list of strings,items.remove(index)with anIntdoesn't compile in Kotlin 2.1: the compiler reports that it is deprecated and says to useremoveAt(index). And with duplicate words, removing by value would take the wrong "call". - Forgetting to keep the item. After
removeAtthe item is gone from the list. Without thevalthere is nothing left to insert. - Insert before remove. Adding at 0 first shifts every item, so the old
indexno longer points at the same item. - Index 0. It works with no special case: remove the first item, add it back at the front.
Testing
["wash", "shop", "cook", "read"],index = 2givescook wash shop read.["tea", "coffee"],index = 0givestea coffee.["call", "pay", "call", "walk"],index = 2givescall call pay walk.
