Problem overview
The function find receives a vector of integers, nums, and an integer value. It returns the index where value sits in nums, or -1 when the value isn't there. The statement sets a budget of O(n) time and O(1) extra space.
For nums = [1, 2, 4, 5] and value = 4, the answer is 2, because nums[2] is 4. For value = 3, nothing matches, so the answer is -1.
Approach: try every position in order
The vector is not promised to be sorted, so the only way to know a value is absent is to look at every element. Linear search does exactly that: it starts at index 0 and moves right, one element at a time, and stops at the first match.
The answer is a position, not a value. A loop that hands you the elements, such as for num in &nums, tells you what each element is but not where it is. So the loop here runs over indices, and the element is read with nums[i].
The value -1 works as the "not found" marker because no real index is negative. Returning it after the loop is safe: the line is reached only when no iteration found a match and returned early.
Step by step
- Loop over the indices. Use
for i in 0..nums.len(). The range stops beforelen(), soitakes every valid index and nothing beyond. - Compare and return. If
nums[i] == value, the search is over. Returni as i32immediately. The early return means a value that appears several times gives its first index. - Return -1 after the loop. The loop ran to the end without finding the value, so report that it is missing.
The solution in Rust
impl Solution {
fn find(nums: Vec<i32>, value: i32) -> i32 {
for i in 0..nums.len() {
if nums[i] == value {
return i as i32;
}
}
return -1;
}
}
The Rust details worth a closer look:
usizeversusi32.0..nums.len()is a range ofusize, the type Rust uses for indices, soiis ausize. The function returns ani32, and Rust never converts between integer types silently. Writingreturn i;is a compile error ("expectedi32, foundusize"). The casti as i32does the conversion.- Casts can truncate.
asdoesn't check the value. Ausizeabovei32::MAXwould wrap to a wrong number. For a vector that can reach billions of elements that matters; for this lesson's inputs it doesn't. - Why
-1is possible. The return type is signed, which is what allows a negative marker. Ausizereturn type couldn't hold it, and that is one reason the function returnsi32. - Comparing integers.
nums[i] == valuecompares twoi32values. Indexing a vector gives the element itself (copied here, sincei32isCopy), so no dereferencing is needed. - Idiomatic alternative. The standard library has
nums.iter().position(|&x| x == value), which returns anOption<usize>:Some(index)orNone. Writing the loop yourself first shows whatpositiondoes.
Complexity
Time: O(n). In the worst case, a missing value or one at the very end, the loop checks all n elements, each in constant time. In the best case, the first element matches and the loop does one check. The bound that holds for every input is O(n).
Space: O(1). The loop keeps one index variable, regardless of how long the vector is. The vector itself is the input and isn't counted as extra space.
Edge cases and common mistakes
- Value not present.
[1, 2, 4, 5]with value 3 returns-1. - Empty vector. The range
0..0is empty, the loop body never runs, and the function returns-1. - Duplicates.
[7, 7, 7]with value 7 returns0. Because the function returns at the first match, it never sees the later ones. - Returning inside the wrong place. Putting
return -1in anelsebranch inside the loop makes the function give up after the first element. The "not found" answer belongs after the loop. - Returning the value instead of the index.
return nums[i]compiles but answers a different question. - Forgetting the cast.
return i;fails to compile becauseiis ausize. - Mixing up the result of a missing value with index 0. The answer for an absent value is
-1, not0, since 0 is a real index.
Testing
nums = [1, 2, 4, 5],value = 4gives2.nums = [1, 2, 4, 5],value = 3gives-1.nums = [7, 7, 7],value = 7gives0.nums = [],value = 3gives-1.
