Given an integer array nums containing N elements and a non-negative integer k, return true when two distinct indices i and j satisfy both conditions:
nums[i] == nums[j]|i - j| <= k
Return false when no valid pair exists.
Example 1
Input: nums = [1, 2, 3, 1], k = 3
Output: true
Explanation: Value 1 occurs at indices 0 and 3. The index distance is |0 - 3| = 3, which does not exceed k.
Example 2
Input: nums = [1, 2, 3, 1, 2, 3], k = 2
Output: false
Explanation: Every repeated value occurs at indices separated by 3 positions. Since 3 > k, no valid pair exists.
Brute Force Approach
Only index pairs separated by at most K positions can satisfy the required distance condition. For an element at index i, positions after i + K cannot form a valid pair with index i.
Comparing every element with the next K eligible elements covers every valid forward pair. A matching pair confirms a nearby duplicate immediately. Completion of all eligible comparisons without equality confirms the absence of a valid pair.
Algorithm
Return
falsewhenN < 2orK = 0, since two distinct indices cannot satisfy the required condition.Traverse every index
ifrom0toN - 1.Traverse index
jfromi + 1tomin(N - 1, i + K), limiting comparisons to valid index distances.Compare
nums[i]withnums[j].Return
trueimmediately when equal values appear within a distance of at mostK.Return
falseafter every eligible pair remains different.
Dry Run
cd2
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: /* Checks every eligible pair within distance k. */ bool containsNearbyDuplicate(vector<int>& nums, int k) { int n = nums.size(); // Handle cases without any valid distinct pair. if (n < 2 || k <= 0) { return false; } // Select the first index of every pair. for (int i = 0; i < n; i++) { // Compare only indices within distance k. for (int j = i + 1; j < n && j - i <= k; j++) { // Stop after finding a nearby duplicate. if (nums[i] == nums[j]) { return true; } } } // No valid duplicate pair exists. return false; }};// Driver code to execute the solution.int main() { vector<int> nums = {1, 2, 3, 1}; int k = 3; Solution solution; bool answer = solution.containsNearbyDuplicate(nums, k); cout << boolalpha << answer << endl; return 0;}Complexity Analysis
Time Complexity: O(N × min(N, K)), where N represents the number of array elements and K represents the maximum allowed index distance. Every index is compared with at most the next K elements. The complexity becomes O(N²) when K is at least N.
Space Complexity: O(1), because only loop indices and the array size are stored.
Better Approach
The Brute Force Approach performs several repeated comparisons for every index. For the current value at index i, only the closest previous occurrence can produce the smallest possible index distance.
A Hash Map named latestIndex stores every processed value with the most recent index containing that value. The name latestIndex describes the stored information directly: every key represents an array value, while the corresponding mapped value represents the latest processed position of that value.
Comparing index i with the latest previous occurrence gives the minimum distance among all earlier equal values. Any older occurrence can only produce an equal or larger distance. After an unsuccessful distance check, replacing the stored position with index i prepares the closest possible occurrence for future comparisons.
Algorithm
Return
falsewhenN < 2orK = 0, since two distinct indices cannot satisfy the required distance condition.Initialize an empty Hash Map
latestIndex. Store every processed array value as a key and the most recent index containing that value as the mapped value. The latest position provides the minimum possible distance from any future equal value.Traverse every index
ifrom0toN - 1.Search for
nums[i]insidelatestIndex.Retrieve the stored previous index when
nums[i]already exists.Calculate the distance between both occurrences using
i - previousIndex.Return
truewhen the calculated distance does not exceedK.Store or update
latestIndex[nums[i]] = iafter an unsuccessful check. The current index becomes the closest previous occurrence for every future appearance of the same value.Return
falseafter the complete traversal finds no valid pair.
Dry Run
cd2
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: /* Stores the latest index of every value. */ bool containsNearbyDuplicate(vector<int>& nums, int k) { int n = nums.size(); // Handle cases without any valid distinct pair. if (n < 2 || k <= 0) { return false; } // Map each value to the latest processed index. unordered_map<int, int> latestIndex; // Process every array index once. for (int i = 0; i < n; i++) { auto entry = latestIndex.find(nums[i]); // Check the distance from the latest occurrence. if ( entry != latestIndex.end() && i - entry->second <= k ) { return true; } // Store the current index as the latest occurrence. latestIndex[nums[i]] = i; } // No valid duplicate pair exists. return false; }};// Driver code to execute the solution.int main() { vector<int> nums = {1, 2, 3, 1}; int k = 3; Solution solution; bool answer = solution.containsNearbyDuplicate(nums, k); cout << boolalpha << answer << endl; return 0;}Complexity Analysis
Time Complexity: O(N) on average, where N represents the number of elements in nums. Every element requires one average O(1) Hash Map lookup and one average O(1) update.
Space Complexity: O(N), because the Hash Map can store one latest index for every distinct array value.
Optimal Approach
The Better Approach reduces the average running time to linear, but the Hash Map can retain values whose stored indices already lie outside the allowed distance. Such entries cannot form a valid pair with the current or any later index.
A Hash Set named window stores values belonging only to the active range of previous K indices. The name window represents the sliding section of the array currently eligible for comparison. Before processing index i, the set contains values from indices max(0, i - K) through i - 1.
A successful membership lookup therefore confirms two facts at once: an equal value has appeared earlier, and the corresponding occurrence lies within the allowed distance. Exact indices become unnecessary because the active window already enforces the distance condition.
Algorithm
Return
falsewhenN < 2orK = 0, since no two distinct indices can have a distance of zero.Initialize an empty Hash Set
windowto represent values stored within the previousKvalid positions. Membership insidewindowacts as both duplicate detection and distance validation.Traverse every index
ifrom0toN - 1.Search for
nums[i]insidewindow.Return
truewhennums[i]already exists, because the matching occurrence belongs to one of the previousKindices.Insert
nums[i]intowindowafter an unsuccessful membership check, making the current value available for upcoming indices.Remove
nums[i - K]wheni >= K. Perform the removal after checking the current index because indexi - Kremains a valid candidate for indexi, but falls outside the allowed range for indexi + 1.Return
falseafter the complete traversal finds no nearby duplicate.
Dry Run
k
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: /* Maintains values from the previous k indices. */ bool containsNearbyDuplicate(vector<int>& nums, int k) { int n = nums.size(); // Handle cases without any valid distinct pair. if (n < 2 || k <= 0) { return false; } // Store values inside the active index window. unordered_set<int> window; // Process every array value once. for (int i = 0; i < n; i++) { // Detect a matching value inside the valid window. if (window.find(nums[i]) != window.end()) { return true; } // Add the current value to the active window. window.insert(nums[i]); // Remove the oldest value before the next step. if (i >= k) { window.erase(nums[i - k]); } } // No valid duplicate pair exists. return false; }};// Driver code to execute the solution.int main() { vector<int> nums = {1, 2, 3, 1}; int k = 3; Solution solution; bool answer = solution.containsNearbyDuplicate(nums, k); cout << boolalpha << answer << endl; return 0;}Complexity Analysis
Time Complexity: O(N) on average, where N represents the number of elements in nums. Every value is inserted, searched, and removed at most once through average O(1) Hash Set operations.
Space Complexity: O(min(N, K)), where K represents the maximum allowed index distance. The Hash Set retains only values belonging to the active window of at most K previous positions.
FAQs about Contains Duplicate II
1. Why is only the most recent index stored in the Hash Map?
The most recent occurrence produces the smallest distance from every future occurrence. When the latest index lies farther than K positions away, every older index also lies farther than K positions away.
2. Why does the Optimal Approach use a Hash Set instead of a Hash Map?
The active sliding window already guarantees the required index distance. Only value membership remains necessary, so storing exact indices becomes unnecessary.
3. What happens when K is 0?
Two distinct indices always have a distance of at least 1. Therefore, no valid pair can exist when K = 0.
4. Why is the oldest value removed after checking the current value?
A value exactly K positions behind the current index still forms a valid pair. Removal before the current comparison would incorrectly discard a valid candidate.
5. Can a plain Hash Set work without maintaining a sliding window?
No. A Hash Set containing every previously processed value can detect duplicates but cannot confirm the required index distance. Removing values outside the last K positions adds the missing distance guarantee.
Be the first to add a comment.