You should aim for a solution with O(n) time and O(n) space, where n is the size of the input array.
Hint 1
A brute force solution would be to check every element against every other element in the array. This would be an O(n^2) solution. Can you think of a better way?
Hint 2
Is there a way to check if an element is a duplicate without comparing it to every other element? Maybe there's a data structure that is useful here.
Hint 3
We can use a hash data structure like a hash set or hash map to store elements we've already seen. This will allow us to check if an element is a duplicate in constant time.
Before attempting this problem, you should be comfortable with:
Hash Sets - The optimal solution uses a hash set for O(1) lookups to detect duplicates efficiently
Sorting - An alternative approach sorts the array to bring duplicates adjacent, then scans linearly
Basic Array Traversal - The brute force approach uses nested loops to compare all pairs of elements
1. Brute Force
Intuition
We can check every pair of different elements in the array and return true if any pair has equal values. This is the most intuitive approach because it directly compares all possible pairs, but it is also the least efficient since it examines every combination.
Algorithm
Iterate through the array using two nested loops to check all possible pairs of distinct indices.
If any pair of elements has the same value, return true.
If all pairs are checked and no duplicates are found, return false.
classSolution:defhasDuplicate(self, nums: List[int])->bool:for i inrange(len(nums)):for j inrange(i +1,len(nums)):if nums[i]== nums[j]:returnTruereturnFalse
publicclassSolution{publicbooleanhasDuplicate(int[] nums){for(int i =0; i < nums.length; i++){for(int j = i +1; j < nums.length; j++){if(nums[i]== nums[j]){returntrue;}}}returnfalse;}}
classSolution{public:boolhasDuplicate(vector<int>& nums){for(int i =0; i < nums.size(); i++){for(int j = i +1; j < nums.size(); j++){if(nums[i]== nums[j]){returntrue;}}}returnfalse;}};
classSolution{/**
* @param {number[]} nums
* @return {boolean}
*/hasDuplicate(nums){for(let i =0; i < nums.length; i++){for(let j = i +1; j < nums.length; j++){if(nums[i]=== nums[j]){returntrue;}}}returnfalse;}}
publicclassSolution{publicboolhasDuplicate(int[] nums){for(int i =0; i < nums.Length; i++){for(int j = i +1; j < nums.Length; j++){if(nums[i]== nums[j]){returntrue;}}}returnfalse;}}
funchasDuplicate(nums []int)bool{for i :=0; i <len(nums); i++{for j := i +1; j <len(nums); j++{if nums[i]== nums[j]{returntrue}}}returnfalse}
class Solution {funhasDuplicate(nums: IntArray): Boolean {for(i in nums.indices){for(j in i +1 until nums.size){if(nums[i]== nums[j]){returntrue}}}returnfalse}}
If we sort the array, then any duplicate values will appear next to each other. Sorting groups identical elements together, so we can simply check adjacent positions to detect duplicates. This reduces the problem to a single linear scan after sorting, making it easy to identify if any value repeats.
Algorithm
Sort the array in non-decreasing order.
Iterate through the array starting from index 1.
Compare the current element with the previous element.
If both elements are equal, we have found a duplicate — return true.
If the loop finishes without detecting equal neighbors, return false.
classSolution:defhasDuplicate(self, nums: List[int])->bool:
nums.sort()for i inrange(1,len(nums)):if nums[i]== nums[i -1]:returnTruereturnFalse
publicclassSolution{publicbooleanhasDuplicate(int[] nums){Arrays.sort(nums);for(int i =1; i < nums.length; i++){if(nums[i]== nums[i -1]){returntrue;}}returnfalse;}}
classSolution{public:boolhasDuplicate(vector<int>& nums){sort(nums.begin(), nums.end());for(int i =1; i < nums.size(); i++){if(nums[i]== nums[i -1]){returntrue;}}returnfalse;}};
classSolution{/**
* @param {number[]} nums
* @return {boolean}
*/hasDuplicate(nums){
nums.sort((a, b)=> a - b);for(let i =1; i < nums.length; i++){if(nums[i]=== nums[i -1]){returntrue;}}returnfalse;}}
publicclassSolution{publicboolhasDuplicate(int[] nums){
Array.Sort(nums);for(int i =1; i < nums.Length; i++){if(nums[i]== nums[i -1]){returntrue;}}returnfalse;}}
funchasDuplicate(nums []int)bool{
sort.Ints(nums)for i :=1; i <len(nums); i++{if nums[i]== nums[i-1]{returntrue}}returnfalse}
class Solution {funhasDuplicate(nums: IntArray): Boolean {
nums.sort()for(i in1 until nums.size){if(nums[i]== nums[i -1]){returntrue}}returnfalse}}
Space complexity: O(1) or O(n) depending on the sorting algorithm.
3. Hash Set
Intuition
We can use a hash set to efficiently keep track of the values we have already encountered. As we iterate through the array, we check whether the current value is already present in the set. If it is, that means we've seen this value before, so a duplicate exists. Using a hash set allows constant-time lookups, making this approach much more efficient than comparing every pair.
Algorithm
Initialize an empty hash set to store seen values.
Iterate through each number in the array.
For each number:
If it is already in the set, return true because a duplicate has been found.
Otherwise, add it to the set.
If the loop finishes without finding any duplicates, return false.
classSolution:defhasDuplicate(self, nums: List[int])->bool:
seen =set()for num in nums:if num in seen:returnTrue
seen.add(num)returnFalse
publicclassSolution{publicbooleanhasDuplicate(int[] nums){Set<Integer> seen =newHashSet<>();for(int num : nums){if(seen.contains(num)){returntrue;}
seen.add(num);}returnfalse;}}
classSolution{public:boolhasDuplicate(vector<int>& nums){
unordered_set<int> seen;for(int num : nums){if(seen.count(num)){returntrue;}
seen.insert(num);}returnfalse;}};
classSolution{/**
* @param {number[]} nums
* @return {boolean}
*/hasDuplicate(nums){const seen =newSet();for(const num of nums){if(seen.has(num)){returntrue;}
seen.add(num);}returnfalse;}}
publicclassSolution{publicboolhasDuplicate(int[] nums){HashSet<int> seen =newHashSet<int>();foreach(int num in nums){if(seen.Contains(num)){returntrue;}
seen.Add(num);}returnfalse;}}
funchasDuplicate(nums []int)bool{
seen :=make(map[int]bool)for_, num :=range nums {if seen[num]{returntrue}
seen[num]=true}returnfalse}
class Solution {funhasDuplicate(nums: IntArray): Boolean {val seen = HashSet<Int>()for(num in nums){if(num in seen){returntrue}
seen.add(num)}returnfalse}}
classSolution{funchasDuplicate(_ nums:[Int])->Bool{var seen =Set<Int>()for num in nums {if seen.contains(num){returntrue}
seen.insert(num)}returnfalse}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
4. Hash Set Length
Intuition
This approach uses the same idea as the previous hash set method: a set only stores unique values, so duplicates are automatically removed. Instead of checking each element manually, we simply compare the length of the set to the length of the original array. If duplicates exist, the set will contain fewer elements. The logic is identical to the earlier approach — this version is just a shorter and more concise implementation of it.
Algorithm
Convert the array into a hash set, which removes duplicates.
Compare the size of the set with the size of the original array.
If the set is smaller, return true because duplicates must have been removed.
When using nested loops, a common mistake is comparing an element with itself by starting the inner loop at i instead of i + 1.
# Wrong: Compares element with itselffor i inrange(len(nums)):for j inrange(len(nums)):# Should start at i + 1if nums[i]== nums[j]:returnTrue# Correct: Skip self-comparisonfor i inrange(len(nums)):for j inrange(i +1,len(nums)):if nums[i]== nums[j]:returnTrue
Modifying Input Array Unexpectedly
The sorting approach modifies the original array, which may not be acceptable in some contexts. If the original order matters, make a copy first.
# Caution: This modifies the input
nums.sort()# Safer: Sort a copy if original order matters
sorted_nums =sorted(nums)