Searching & SortingProblem 9 of 36
Searching in an array where adjacent differ by at most k
Problem Statement
Given an array where adjacent elements differ by at most k, search for a given element x. If x is present, return its index; otherwise, return -1.
Constraints:
- Adjacent elements differ by at most k: |arr[i] - arr[i+1]| <= k
- Array is not necessarily sorted
- k >= 1
Example:
- Input:
arr = [4, 5, 6, 7, 6],k = 1,x = 6 - Output:
2(or4, since 6 appears at both indices) - Explanation: 6 is found at index 2
Example 2:
- Input:
arr = [20, 40, 50, 70, 70, 60],k = 20,x = 60 - Output:
5 - Explanation: 60 is found at index 5
Approach 1: Brute Force (Linear Search)
Intuition
Simply scan through all elements to find the target.
Algorithm
- Traverse the array from index 0 to n-1
- If current element equals x, return index
- Return -1 if not found
java
public class Solution {
public int search(int[] arr, int x) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == x) {
return i;
}
}
return -1;
}
}Complexity Analysis
- Time Complexity: O(n) - May need to check all elements
- Space Complexity: O(1) - No extra space
Approach 2: Jump Search Based on Difference (Optimal)
Intuition
Since adjacent elements differ by at most k, we can calculate the minimum number of steps needed to reach x from the current element and jump directly.
Key Insight:
- If
arr[i] = aand we're looking forx - Difference = |x - a|
- Minimum steps to reach x = ceil(|x - a| / k)
- We can safely skip to index
i + max(1, |x - a| / k)
Algorithm
- Start from index i = 0
- If arr[i] == x, return i
- Calculate jump = max(1, |arr[i] - x| / k)
- Move i += jump
- Repeat until i >= n
- Return -1 if not found
java
public class Solution {
public int searchWithJump(int[] arr, int k, int x) {
int n = arr.length;
int i = 0;
while (i < n) {
// Found the element
if (arr[i] == x) {
return i;
}
// Calculate minimum steps needed
int diff = Math.abs(arr[i] - x);
int jump = Math.max(1, diff / k);
i += jump;
}
return -1;
}
}Dry Run Example
arr = [20, 40, 50, 70, 70, 60], k = 20, x = 60
i = 0:
arr[0] = 20 != 60
diff = |20 - 60| = 40
jump = max(1, 40/20) = 2
i = 0 + 2 = 2
i = 2:
arr[2] = 50 != 60
diff = |50 - 60| = 10
jump = max(1, 10/20) = max(1, 0) = 1
i = 2 + 1 = 3
i = 3:
arr[3] = 70 != 60
diff = |70 - 60| = 10
jump = max(1, 10/20) = max(1, 0) = 1
i = 3 + 1 = 4
i = 4:
arr[4] = 70 != 60
diff = |70 - 60| = 10
jump = max(1, 10/20) = max(1, 0) = 1
i = 4 + 1 = 5
i = 5:
arr[5] = 60 == 60
FOUND! Return 5
Why This Works
arr = [4, 5, 6, 7, 6], k = 1
Looking for x = 6, starting at i = 0, arr[0] = 4
Since adjacent elements differ by at most 1:
- To go from 4 to 6, we need at least |6-4|/1 = 2 steps
- So we can safely jump 2 positions
arr[0]=4 → arr[1] can be 3,4,5 (at most k=1 away)
→ arr[2] can be 2,3,4,5,6 (at most 2k away from arr[0])
If x=6 exists and arr[0]=4, it cannot be at index 1
It CAN be at index 2 or beyond
Complexity Analysis
- Time Complexity: O(n/k) average case
- In the worst case (x is at the end, values oscillate), it's O(n)
- In the best case, we jump in large steps
- Space Complexity: O(1) - Only using variables
Finding All Occurrences
Variation: Bidirectional Search
Start from both ends and meet in the middle.
Edge Cases
Comparison with Standard Approaches
| Approach | Time Complexity | When to Use | |----------|----------------|-------------| | Linear Search | O(n) | Always works | | Jump Search | O(n/k) avg | Adjacent differ by ≤ k | | Binary Search | O(log n) | Sorted array | | Hash Table | O(1) avg | Preprocessing allowed |
Key Takeaways
- Constraint Exploitation: The constraint |arr[i] - arr[i+1]| <= k allows smart jumping
- Jump Calculation: jump = max(1, |current - target| / k) is the key formula
- Safe Skipping: We can safely skip positions because target can't exist there
- Average Case: O(n/k) is much better than O(n) when k is small
- Worst Case: Still O(n) when values oscillate around target
- Applications: Step-limited search, constrained sequences, sensor data with limited change rate