Problem overview
The function find receives a slice of integers, nums, and an integer value. It returns the index where value sits, or -1 if the value isn't in the slice. For nums = [1, 2, 4, 5] and value = 4 the answer is 2, because nums[2] is 4.
The task sets a budget of O(n) time and O(1) extra space, which a single pass over the slice meets.
Approach
Linear search checks the elements one by one, from the first, until one equals value. At that moment the position is known and the function can return it. If the loop ends without a match, the value is not present.
The question asks for a position, not for the value itself. A range loop that takes the element, as in for _, num := range nums, tells you the value of each element but loses its position. Taking the index instead solves this: the index is available in the loop, and the element is just nums[i].
Step by step
- Loop with
range, keeping only the index. Whenrangeover a slice is given a single variable, that variable is the index, not the element.for i := range numstherefore walks through0, 1, 2, ...up to the last index. - Compare and return. Inside the loop, if
nums[i] == value, returniimmediately. Returning ends the function, so the search stops at the first match. If the value appears more than once, the caller gets its first index. - Return -1 after the loop. The line below the loop runs only if the loop finished without returning. That means no element matched. The value -1 can never be a real index, so the caller can tell "not found" from any valid answer.
The solution in Go
func find(nums []int, value int) int {
for i := range nums {
if nums[i] == value {
return i
}
}
return -1
}
The Go details worth knowing:
- One variable versus two.
for i := range numsgives the index.for _, num := range numsgives the element and discards the index.for i, num := range numsgives both, and then both must be used. - Equivalent counting loop.
for i := 0; i < len(nums); i++does the same job. Therangeform cannot run past the end by accident. - The function needs a final
return. Go reports "missing return" if a function with a result can reach its closing brace without returning. The loop alone doesn't satisfy that rule, since the compiler can't know that it will return, soreturn -1is required. - Comparing with
==. Forintvalues==compares the numbers. Comparing a slice with another slice using==is not allowed, but nothing like that happens here.
Complexity
Time: O(n). In the worst case, the value is last or missing, and the loop performs n comparisons, where n is the length of the slice. When the value is first, it takes one. The bound is for the worst case.
Space: O(1). The only extra memory is the loop index.
Linear search works on any slice, sorted or not. If the slice is sorted, binary search can find the value in O(log n), but this lesson doesn't assume sorted data.
Edge cases and common mistakes
- Value not present.
[1, 2, 4, 5]with 3 returns -1. - Duplicates.
[7, 7]with 7 returns 0, the first index. - Empty or
nilslice. The loop does not run and the function returns -1. - Returning -1 inside the loop. An
else { return -1 }on theifwould give up after the first element that doesn't match. The -1 belongs after the loop. - Returning the element.
return nums[i]would give back the value, which the caller already has.
Testing
[]int{1, 2, 4, 5}with 4 gives2.[]int{1, 2, 4, 5}with 3 gives-1.[]int{7, 7}with 7 gives0.[]int{}with 1 gives-1.