Problem overview
The function removeRepeats receives an array of integers nums and returns a new array in which each value appears once. The first copy of each value stays, later copies are dropped, and the values keep the order in which they first appear.
For [3, 1, 3, 2, 1] the result is [3, 1, 2]: the second 3 and the second 1 are repeats. For [6, 6, 6, 6] the result is [6], and for [4, 9, 2] nothing repeats, so the result is [4, 9, 2].
Approach: remember what you have seen
Read the numbers from left to right. For each one, ask whether it has been met before. If not, it is the first copy, so it goes into the result. If so, skip it. A set answers "have I met this value?" quickly, so it is the right place to keep the values seen so far.
You might be tempted to build Set(nums) and convert it back to an array. That removes the repeats, but a Swift set has no order, so the values could come out in any order, and the lesson needs the first-appearance order. The set is used only for the question "seen or not", and the array keeps the order.
Step by step
- Create
seen, an emptySet<Int>()declared withvar. - Create
result, an empty[Int]declared withvar. - Loop over
numsfrom left to right, so the first copy of each value is the one met first. - Check for a new value with
!seen.contains(num). The!turns "is in the set" into "is not in the set". - Append it to
result. Adding at the end keeps the first-appearance order. - Insert it into
seen, so a later copy is skipped. - Return
resultafter the loop. Returning inside the loop would give back only the first value.
The solution in Swift
class Solution {
func removeRepeats(_ nums: [Int]) -> [Int] {
var seen = Set<Int>()
var result = [Int]()
for num in nums {
if !seen.contains(num) {
result.append(num)
seen.insert(num)
}
}
return result
}
}
The empty array is written [Int](), and the empty set Set<Int>(). Both need var because they grow. The result is a new array: the input nums is never changed, since function parameters in Swift are constants.
Watching the loop
On [3, 1, 3, 2, 1], the result grows like this as each number is read:
| Number | Result afterwards |
|---|---|
| 3 | [3] |
| 1 | [3, 1] |
| 3 | [3, 1] |
| 2 | [3, 1, 2] |
| 1 | [3, 1, 2] |
The second 3 and the second 1 find their values already in seen, so the if skips them.
Testing
These calls give:
[3, 1, 2]
[6]
[4, 9, 2]
for the inputs [3, 1, 3, 2, 1], [6, 6, 6, 6] and [4, 9, 2].
Edge cases
A single number returns an array with that number: [8] gives [8]. Negative values and large ones are ordinary integers here, because a Swift Int is 64 bits and the lesson's values stay within a billion in size. [-1000000000, 5, -1000000000, 1000000000, 1000000000] gives [-1000000000, 5, 1000000000].
Common mistakes
- Converting through
Setand back.Array(Set(nums))has the right values but not a reliable order, so the lesson's tests can fail on some runs. - Forgetting to insert into
seen. Then nothing is ever recorded, and every value is treated as new. - Inserting into
seenbut appending outside theif. Then repeats reach the result. - Keeping the last copy. Looping from the right would keep the last copy, but the lesson wants the first.
