/*
Problem: Minimum Problems Solved Before Range Exceeds K
Company Tag: IBM OA
Problem Statement:
We are given an integer array nums and an integer k.
The student must solve problem 0 first.
If the student solved problem i, next problem can be:
i + 1
i + 2
The student stops as soon as:
max(solved values) - min(solved values) > k
Return minimum number of problems solved before stopping.
If impossible, return -1.
Constraints:
Exact constraints were not mentioned.
This solution is O(n), so it works for large arrays.
Brute Force:
Try all possible paths using jumps of 1 or 2.
Why Brute Force Fails:
Number of paths grows exponentially.
Optimized Idea:
Range exceeds k when two solved problems p and j satisfy:
abs(nums[p] - nums[j]) > k
I process j from left to right.
For previous indices, I maintain:
minimum value at even indices
maximum value at even indices
minimum value at odd indices
maximum value at odd indices
Explanation Block:
The cost to include both p and j in a valid path depends only on:
- j
- parity of p
That is why I store min/max values separately for even and odd indices.
If current nums[j] differs from previous min/max by more than k,
then stopping is possible at j.
Dry Run:
nums = [5, 6, 7, 20]
k = 3
At index 3:
nums[3] = 20
previous minimum = 5
20 - 5 = 15 > 3
One path:
0 -> 1 -> 3
Solved values:
5, 6, 20
Answer = 3
Time Complexity:
O(n)
Space Complexity:
O(1)
*/
#include <bits/stdc++.h>
using namespace std;
int minimumProblemsBeforeRangeExceedsK(vector<long long>& nums, long long k) {
int n = nums.size();
const int INF = 1e9;
// mn[0], mx[0] store min/max values at even indices.
// mn[1], mx[1] store min/max values at odd indices.
vector<long long> mn(2, LLONG_MAX);
vector<long long> mx(2, LLONG_MIN);
// Problem 0 is always solved first.
mn[0] = nums[0];
mx[0] = nums[0];
int ans = INF;
for (int j = 1; j < n; j++) {
long long x = nums[j];
for (int parity = 0; parity <= 1; parity++) {
if (mn[parity] == LLONG_MAX) {
continue;
}
bool badPair = false;
// Current value is much larger than previous minimum.
if (mn[parity] < x - k) {
badPair = true;
}
// Current value is much smaller than previous maximum.
if (mx[parity] > x + k) {
badPair = true;
}
if (badPair) {
// Minimum solved count to reach j using jumps of 1 or 2.
int solved = (j + 1) / 2 + 1;
// If j is even and previous index has odd parity,
// one extra solved problem is needed.
if (j % 2 == 0 && parity == 1) {
solved++;
}
ans = min(ans, solved);
}
}
// Add current index for future checks.
int p = j % 2;
mn[p] = min(mn[p], x);
mx[p] = max(mx[p], x);
}
if (ans == INF) {
return -1;
}
return ans;
}
int main() {
vector<long long> nums = {5, 6, 7, 20};
long long k = 3;
cout << minimumProblemsBeforeRangeExceedsK(nums, k) << endl;
return 0;
}