Problem overview
The method find receives an array of numbers, nums, and a number, value. It returns the index where value sits in the array, or -1 if value isn't there. For nums = [1, 2, 4, 5] and value = 4 the answer is 2, because nums[2] is 4.
The statement sets the limits: O(n) time and O(1) extra space. That fits the simplest idea: look at the elements one after another until you find the one you want.
Approach: check each position in order
This is a linear search. Start at index 0 and compare each element with value. The moment one matches, you know the answer and can return its index right away. If the loop reaches the end of the array without a match, the value isn't present, so the method returns -1.
The method needs the index, not just the value, and that's the reason this lesson uses a loop over indices. A for...of loop would give the elements, but would not tell you where you are. Counting with an index i gives you both: the position i and the element nums[i].
Linear search needs no preparation, and it works on any array, sorted or not. If the array were sorted, a faster approach like binary search could skip most elements, but that is a different lesson.
Step by step
- Write the loop. Start
iat 0 and run whilei < nums.length. The last valid index isnums.length - 1, so the condition uses<. - Compare in the loop. Check
nums[i] === value. When it's true,return iimmediately: the position is found, and the loop has no more work. Because the loop returns at the first match, a value that appears several times gives its first index. - Return -1 below the loop. This line is reached only when the loop finished without returning. Since -1 can never be a real index, the caller can tell "not found" from any actual position.
The solution in TypeScript
class Solution {
find(nums: number[], value: number): number {
for (let i = 0; i < nums.length; i++) {
if (nums[i] === value) {
return i;
}
}
return -1;
}
}
The TypeScript points to know:
- Strict equality.
===compares without converting types, so a stray string never matches a number. It is the usual choice in TypeScript. - Returning from inside a loop. A
returnends the whole method, not just the current pass, so the remaining elements are never examined. - Types are compile-time only. The annotations on
numsandvalueare removed from the JavaScript, so nothing stops a wrong type from arriving at run time, for example from parsed JSON. With===a mismatched type simply fails to match. - The built-in way. Arrays have an
indexOfmethod that does the same job,[1, 2, 4, 5].indexOf(4)gives2, and a missing value gives-1. Writing the loop yourself shows what such a method does.
Complexity
Time: O(n), where n is the length of nums. In the worst case, when the value is last or absent, the loop makes n comparisons. Finding it early stops sooner, but the bound is for the worst case.
Space: O(1). The method keeps only the index i.
Edge cases and common mistakes
- The value is missing.
find([1, 2, 4, 5], 3)reaches the final line and returns-1. - An empty array. The loop condition is false at once, so the method returns
-1. - Duplicates.
find([7, 7], 7)returns0, the first position, because the loop returns at the first match. - Putting
return -1inside the loop. It would give up after checking only the first element, sofind([1, 2, 4, 5], 4)would return-1. - Returning the value instead of the index.
return nums[i]would return 4 in the example, not 2. - Using
<=in the loop condition. Ati = nums.length,nums[i]isundefined. That doesn't crash, but it is a wasted pass and a sign of an off-by-one error. NaN.NaN === NaNis false, sofind([NaN], NaN)returns-1. The lesson's inputs are ordinary integers, so this is only a curiosity.
Testing
find([1, 2, 4, 5], 4)gives2.find([1, 2, 4, 5], 3)gives-1.find([7, 7], 7)gives0.find([], 1)gives-1.find([9], 9)gives0.