Problem overview
The method contains receives an Array[Int] named nums and an Int named value. It returns true if value occurs somewhere in nums and false otherwise. The task asks you to write the search yourself, so library helpers that do it for you are off the table.
For example, contains([1, 2, 4, 5], 4) is true because 4 is the third element. contains([-1, 2, -4, 0, 10], 7) is false, because none of the five elements equals 7.
Approach: linear search
An unsorted array gives no hint about where a value might be, so the only way to be sure is to look at the elements one by one and compare each with value. This is called a linear search.
The search can stop early. The moment one element matches, the answer is true and the remaining elements don't matter. The answer can be false only after every element has been checked and none matched. This asymmetry is what shapes the code: the check inside the loop returns true, and the false comes after the loop.
Step by step
- Loop over the elements.
for (num <- nums)binds each element tonumin turn, in index order. - Compare and return early. If
num == value, returntrueat once. This ends the whole method, so nothing after the match is examined. - Return
falseafter the loop. The line after the loop runs only if no element matched, so it needs noelse. An empty array falls straight through to it.
The solution in Scala
class Solution {
def contains(nums: Array[Int], value: Int): Boolean = {
for (num <- nums) {
if (num == value) {
return true
}
}
return false
}
}
The Scala details worth knowing:
==compares values. ForIntit checks whether the two numbers are equal. The same operator also compares strings and other values by content.- Explicit
return. Idiomatic Scala usually leaves outreturnand lets the last expression be the result. This loop is a good case for it, though, because the method must stop in the middle of the iteration. - A compiler warning. The body of a
forloop is a function that Scala passes toforeach, and areturninside it must jump out of the enclosing method. Scala 3.5 accepts this and the method works, but the compiler prints a warning that non-local returns are deprecated and thatboundaryandboundary.breakfromscala.utilare the replacement. The warning does not change the result. - Why the method needs a final
return false. Aforloop withoutyieldhas the typeUnit. If the last thing in the method were the loop, the compiler would reject the method, because it declares aBooleanresult. - A library shortcut exists.
nums.contains(value)andnums.exists(_ == value)do the same job in one line. The exercise asks for the loop, because writing it teaches the pattern.
Complexity
Time: O(n). In the worst case the value is the last element or absent, and the loop makes one comparison for each of the n elements. In the best case the first element matches and the method stops after one comparison.
Space: O(1). The method only uses the loop variable, and nothing grows with the input size.
Edge cases and common mistakes
- Empty array. The loop body never runs and the method returns
false, which is right because nothing can occur in an empty array. - Value at either end. Matches in the first or last position are found like any other.
- Duplicates. The method stops at the first match, so how many times the value appears makes no difference.
- Returning
falseinside the loop. Anelse { return false }branch makes the method answer after looking at only the first element.contains([1, 2, 4, 5], 4)would wrongly givefalse. - Negative numbers. They compare like any other numbers, so
contains([-1, 2, -4, 0, 10], -4)istrue.
Testing
contains(Array(1, 2, 4, 5), 4)givestrue.contains(Array(-1, 2, -4, 0, 10), 7)givesfalse.contains(Array(), 3)givesfalse.
