Problem overview
The function find receives an IntArray named nums and an Int named value. It returns the index at which value sits in nums, or -1 if the value isn't there. The lesson asks for O(n) time and O(1) extra space.
In the example, nums = [1, 2, 4, 5] and value = 4. The value 4 is at index 2, because nums[2] is 4, so the function returns 2. For value = 3 the result would be -1.
Approach: check the elements one by one
This is linear search. You look at the first element, then the second, and so on, stopping as soon as you find a match. If you reach the end without a match, the value isn't present.
Nothing is assumed about the order of the array, so no element can be skipped: any one of them could be the match. In the worst case, when the value is at the end or missing, you look at all n elements, which is the O(n) the lesson asks for. If the array were sorted, a faster method called binary search would be possible, but this lesson doesn't rely on order.
A loop that visits only the values, like for (num in nums), tells you whether a match exists but not where. Because the answer is a position, the loop has to run over positions, the indices.
Step by step
- Loop over the indices.
for (i in nums.indices)makesitake each valid position from 0 tonums.size - 1, and you read the element withnums[i]. - Test each element and return the index at once. If
nums[i] == value, the search is over. Returningiinside the loop ends the function immediately, so the first match wins. When the value appears several times, the function returns the lowest index. - Return
-1after the loop. The line runs only if no iteration returned, which means every element differed fromvalue. The number -1 can never be a real index, so the caller can tell "not found" from a genuine position.
The solution in Kotlin
class Solution {
fun find(nums: IntArray, value: Int): Int {
for (i in nums.indices) {
if (nums[i] == value) {
return i
}
}
return -1
}
}
The Kotlin details behind it:
nums.indices. It is the range0..nums.size - 1, built for you. In Kotlin the length of an array is the propertysize, notlength. Writingnums.lengthis a compile error. For an empty array,indicesis an empty range, so the loop body never runs.- Return from inside a loop. A
returnleaves the whole function, not just the loop. That is what makes the search stop early. ==compares values. ForIntelements,nums[i] == valueasks whether the two numbers are equal.- The function must return on every path. The final
return -1is required. The compiler can't know that the loop will find a match, and without it the function would not compile. - A built-in exists.
nums.indexOf(value)does the same job and returns -1 when the value is missing. Writing the loop yourself shows how it works.
Complexity
Let n be the length of nums.
Time: O(n). The loop runs at most n times, with one comparison each. The best case is a match at index 0, which takes a single comparison. The worst case, a missing value or a match at the last position, takes n.
Space: O(1). The only extra storage is the loop variable i.
Edge cases and common mistakes
- The value is missing.
[1, 2, 4, 5]withvalue = 3returns-1. - An empty array. The loop doesn't run, so the result is
-1. - Repeated values.
[7, 7, 7]withvalue = 7returns 0, the first index. - Value at index 0. The function returns 0, which is a valid answer and different from -1. A caller must test for "not found" with
result == -1, not with a check for zero. - Returning the element instead of the index.
return nums[i]would returnvalueitself, which is the number you already knew. - Putting
return -1inside the loop. The function would give up after the first element that doesn't match. The "not found" answer can be given only after all elements have been checked. - Unsorted input. It doesn't matter.
[9, -1, 5]withvalue = 5returns 2.
Testing
nums = [1, 2, 4, 5],value = 4gives2.nums = [1, 2, 4, 5],value = 3gives-1.nums = [],value = 3gives-1.nums = [7, 7, 7],value = 7gives0.nums = [9, -1, 5],value = 9gives0.