Check for Array Contains Duplicate III
Last Updated :
24 May, 2024
Given an integer array arr[] and two integers indexDifference and valueDifference, find a pair of indices (i, j) such that:
- i != j
- abs(i - j) <= indexDifference
- abs(arr[i] - arr[j]) <= valueDifference
Return true if such a pair exists, false otherwise.
Example:
Input: arr = [1,2,3,1], indexDifference = 3, valueDifference = 0
Output: true
Explanation: We can choose (i, j) = (0, 3).
We satisfy the three conditions:
- i != j --> 0 != 3
- abs(i - j) <= indexDifference --> abs(0 - 3) <= 3
- abs(arr[i] - arr[j]) <= valueDifference --> abs(1 - 1) <= 0
Input: arr = [1,5,9,1,5,9], indexDifference = 2, valueDifference = 3
Output: false
Explanation: After trying all the possible pairs (i, j), we cannot satisfy the three conditions, so we return false.
Approach:
The idea is to uses a sliding window approach with a multiset to efficiently find such a pair.
Main points:
- Sliding window: A window of size k+1 slides through the array. This window keeps track of the elements within a distance of k from the current element.
- Multiset: The window is implemented as a multiset, which stores the elements in sorted order. This allows for efficient retrieval of the closest elements to the current element.
- Checking for valid pairs: For each element in the window, the solution checks if there exists another element within the window that satisfies the given constraints. This is done by finding the upper and lower bounds of the current element in the multiset and comparing their absolute differences with the given t.
- Sliding the window: After checking for a valid pair, the window slides forward by removing the leftmost element and adding the next element from the array.
Steps-by-step approach:
- Create a multiset called window to store elements in sorted order.
- Initialize two indices, i and j, both starting at 0.
- Loop through the array using j as the index.
- For each element arr[j]:
- Find the upper bound of arr[j] in the window using upper_bound.
- If the upper bound exists and the absolute difference between it and arr[j] is less than or equal to t, return true.
- If the upper bound doesn't exist or the difference is greater than t, check the lower bound.
- Find the lower bound of arr[j] in the window using upper_bound (with a slight adjustment) and check the difference.
- If the lower bound exists and the absolute difference between it and arr[j] is less than or equal to t, return true.
- If no valid pair is found within the window, insert arr[j] into the window.
- If the window size exceeds k+1, remove the leftmost element (arr[i]) from the window and increment i.
- Increment j to move the window forward.
- If the loop completes without finding a valid pair, return false.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k,
int t)
{
// Create a multiset to store the window elements in
// sorted order
multiset<int> window;
// Initialize window size and indices
int n = nums.size();
int i = 0, j = 0;
// Iterate through the array
while (j < n) {
// Check if there exists a valid pair within the
// window
auto upper = window.upper_bound(
nums[j]); // Find the upper bound of nums[j] in
// the window
if ((upper != window.end() && *upper - nums[j] <= t)
|| // Check if the upper bound satisfies the
// constraints
(upper != window.begin()
&& nums[j] - *(--upper)
<= t)) { // Check if the lower bound
// satisfies the constraints
return true;
}
// Insert the current element into the window
window.insert(nums[j]);
// Maintain the window size
if (window.size() == k + 1) {
// Remove the leftmost element from the window
window.erase(nums[i]);
i++;
}
// Move the window forward
j++;
}
// No valid pair found
return false;
}
int main()
{
vector<int> nums = { 1, 2, 3, 1 };
int k = 3;
int t = 0;
bool result = containsNearbyAlmostDuplicate(nums, k, t);
if (result) {
cout << "There exists a pair of indices satisfying "
"the constraints."
<< endl;
}
else {
cout << "No such pair exists." << endl;
}
return 0;
}
Java
import java.util.TreeSet;
class ContainsNearbyAlmostDuplicate {
public static boolean
containsNearbyAlmostDuplicate(int[] nums, int k, int t)
{
TreeSet<Long> window = new TreeSet<>();
int n = nums.length;
int i = 0, j = 0;
while (j < n) {
Long floor = window.floor((long)nums[j] + t);
Long ceil = window.ceiling((long)nums[j] - t);
if ((floor != null && floor >= nums[j])
|| (ceil != null && ceil <= nums[j])) {
return true;
}
window.add((long)nums[j]);
if (window.size() == k + 1) {
window.remove((long)nums[i]);
i++;
}
j++;
}
return false;
}
public static void main(String[] args)
{
int[] nums = { 1, 2, 3, 1 };
int k = 3;
int t = 0;
boolean result
= containsNearbyAlmostDuplicate(nums, k, t);
if (result) {
System.out.println(
"There exists a pair of indices satisfying the constraints.");
}
else {
System.out.println("No such pair exists.");
}
}
}
Python
from sortedcontainers import SortedList
def containsNearbyAlmostDuplicate(nums, k, t):
# Create a sorted list to store the window elements in
window = SortedList()
# Initialize window size and indices
n = len(nums)
i, j = 0, 0
# Iterate through the array
while j < n:
# Check if there exists a valid pair within the window
# Find the upper bound of nums[j] in the window
upper = window.bisect_right(nums[j])
if (upper < len(window) and window[upper] - nums[j] <= t) or \
(upper > 0 and nums[j] - window[upper - 1] <= t):
# Check if the upper bound satisfies the constraints
return True
# Insert the current element into the window
window.add(nums[j])
# Maintain the window size
if len(window) == k + 1:
# Remove the leftmost element from the window
window.remove(nums[i])
i += 1
# Move the window forward
j += 1
# No valid pair found
return False
def main():
nums = [1, 2, 3, 1]
k = 3
t = 0
result = containsNearbyAlmostDuplicate(nums, k, t)
if result:
print("There exists a pair of indices satisfying the constraints.")
else:
print("No such pair exists.")
if __name__ == "__main__":
main()
JavaScript
function containsNearbyAlmostDuplicate(nums, k, t) {
const window = new Set();
let i = 0,
j = 0;
while (j < nums.length) {
let found = false;
for (let num of window) {
if (Math.abs(num - nums[j]) <= t) {
found = true;
break;
}
}
if (found) return true;
window.add(nums[j]);
if (window.size > k) {
window.delete(nums[i]);
i++;
}
j++;
}
return false;
}
// Main execution starts here
const nums = [1, 2, 3, 1];
const k = 3;
const t = 0;
const result = containsNearbyAlmostDuplicate(nums, k, t);
if (result) {
console.log("There exists a pair of indices satisfying the constraints.");
} else {
console.log("No such pair exists.");
}
OutputThere exists a pair of indices satisfying the constraints.
Time complexity : O(N log k)
Auxiliary Space: O(k)
Similar Reads
DSA Tutorial - Learn Data Structures and Algorithms DSA (Data Structures and Algorithms) is the study of organizing data efficiently using data structures like arrays, stacks, and trees, paired with step-by-step procedures (or algorithms) to solve problems effectively. Data structures manage how data is stored and accessed, while algorithms focus on
7 min read
Non-linear Components In electrical circuits, Non-linear Components are electronic devices that need an external power source to operate actively. Non-Linear Components are those that are changed with respect to the voltage and current. Elements that do not follow ohm's law are called Non-linear Components. Non-linear Co
11 min read
Quick Sort QuickSort is a sorting algorithm based on the Divide and Conquer that picks an element as a pivot and partitions the given array around the picked pivot by placing the pivot in its correct position in the sorted array. It works on the principle of divide and conquer, breaking down the problem into s
12 min read
Merge Sort - Data Structure and Algorithms Tutorials Merge sort is a popular sorting algorithm known for its efficiency and stability. It follows the divide-and-conquer approach. It works by recursively dividing the input array into two halves, recursively sorting the two halves and finally merging them back together to obtain the sorted array. Merge
14 min read
Bubble Sort Algorithm Bubble Sort is the simplest sorting algorithm that works by repeatedly swapping the adjacent elements if they are in the wrong order. This algorithm is not suitable for large data sets as its average and worst-case time complexity are quite high.We sort the array using multiple passes. After the fir
8 min read
Data Structures Tutorial Data structures are the fundamental building blocks of computer programming. They define how data is organized, stored, and manipulated within a program. Understanding data structures is very important for developing efficient and effective algorithms. What is Data Structure?A data structure is a st
2 min read
Breadth First Search or BFS for a Graph Given a undirected graph represented by an adjacency list adj, where each adj[i] represents the list of vertices connected to vertex i. Perform a Breadth First Search (BFS) traversal starting from vertex 0, visiting vertices from left to right according to the adjacency list, and return a list conta
15+ min read
Binary Search Algorithm - Iterative and Recursive Implementation Binary Search Algorithm is a searching algorithm used in a sorted array by repeatedly dividing the search interval in half. The idea of binary search is to use the information that the array is sorted and reduce the time complexity to O(log N). Binary Search AlgorithmConditions to apply Binary Searc
15 min read
Insertion Sort Algorithm Insertion sort is a simple sorting algorithm that works by iteratively inserting each element of an unsorted list into its correct position in a sorted portion of the list. It is like sorting playing cards in your hands. You split the cards into two groups: the sorted cards and the unsorted cards. T
9 min read
Dijkstra's Algorithm to find Shortest Paths from a Source to all Given a weighted undirected graph represented as an edge list and a source vertex src, find the shortest path distances from the source vertex to all other vertices in the graph. The graph contains V vertices, numbered from 0 to V - 1.Note: The given graph does not contain any negative edge. Example
12 min read