Problem statement
Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct.
Link to problem
Example 1
Input: nums = [1,2,3,1]
Output: true
Example 2
Input: nums = [1,2,3,4]
Output: false
Example 3
Input: nums = [1,1,1,3,3,4,3,2,4,2]
Output: true
Solutions
Approach 1: HashSet
A hash set implemented as a HashMap where the value is (), aka just keys, and no values.
Very similar to what we did in Two Sum, we iterate over the array and add elements into a hashset, but if an element already exists in the hashset, we immediately return true.
Implementation in Rust
use std::collections::HashSet;
fn contains_duplicate(numbers: Vec<i32>) -> bool {
let mut results = HashSet::new();
for item in numbers {
if results.contains(&item) {
return true;
}
results.insert(item);
}
false
}
Time Complexity: $O(n)$
Space Complexity: $O(n)$
Runtime on LeetCode: $24$ms
You might have noticed that the above implementation would work with any collections construct such as vectors, arrays and hashmaps, it is not just limited to HashSets.
It can be modified to make full use of HashSet because HashSets do not allow duplicates, we could take advantage of this construct by adding all elements into the hashset and comparing the length of hashset and our input array.
Implementation in Rust
fn contains_duplicate(numbers: Vec<i32>) -> bool {
let resultant_set:HashSet<&i32> = HashSet::from_iter(numbers.iter());
!(&resultant_set.len() == &numbers.len())
}
Runtime on LeetCode: $17$ms
Approach 2: Looping
What one would use if there was a space constraint, this approach has $O(1)$ space complexity but that is overshadowed by it’s $O(n^2)$ time complexity.
Valid approach if you have limited memory but time to spare.
Pseudocode
begin a loop
select ith element
begin a loop
compare ith element with rest of the elements
if found
return true
return false
Implementation in Rust
fn contains_duplicate(numbers: Vec<i32>) -> bool {
for i in 0..(numbers.len()) {
for j in 0..(numbers.len()) {
if i != j {
if numbers[i] == numbers[j] {
return true;
}
}
}
}
false
}
Time Complexity: $O(n)$
Runtime on LeetCode: Time Limit Exceeded
Approach 3: Sorting
What happens when you sort a vector? The duplicate elements appear next to each other!
So we first sort the array then look at it for adjacent duplicates.
Implementation in Rust
fn contains_duplicate(numbers: Vec<i32>) -> bool {
let mut sorted = numbers.clone();
sorted.sort();
for i in 0..(sorted.len() - 1) {
if sorted[i] == sorted[i+1] {
return true
}
}
false
}
Time Complexity: $O(n logn)$
Space Complexity: $O(n)$
Runtime on LeetCode: $26$ms