Using 2nd hint: Time: O(n + n log(k)), Memory: O(n + k). Where n is the size of nums and k is the indexDiff
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int indexDiff, int valueDiff) {
int n = nums.size();
// Make a vector of pairs. Each pair is the value in nums and its index.
vector<pair<int, int>> numAndIndexVector(n);
for(int ii=0; ii<n; ++ii)
{
numAndIndexVector[ii] = pair<int, int>{nums[ii], ii};
}
// Evaluate a chunk of numAndIndexVector to see if any of its values and their indices are within the
// valueDiff and indexDiff criteria.
int chunk = (2 * (indexDiff+1));
// sortedArray will be a vector (of size chunk) of sorted pairs.
vector<pair<int, int>> sortedArray(chunk);
// At each iteration. Take a chunk of values from numAndIndexVector put them into sortedArray and sort them.
// Then test each pair against the adjacent pair. Check if this pair's index compared with the adjacent pair's index
// are within indexDiff and similarly that the values are within valueDiff.
// If adjacent pairs do not have indexes within indexDiff, then move the to the next adjacent pair, compare this test pair
//with the next adjacent pair.
// All pairs are tested against all pairs in this chunk.
// Only increase ii by chunk/2. The pairs that were originally at the end of the chunk
// in numAndIndexVector still need to be tested against the pairs in the next chunk. So include the last half of this chunk in
// the next chunk. So the beginning of the chunk in numAndIndexVector was tested in the last iteration
// against pairs in the last chunk and is now tested against pairs in this chunk.
for(int ii=0; ii<n; ii+=(chunk/2))
{
// Populating sortedArray. If there's not enough pairs, then only go to end of the numAndIndexVector.
// The last sortedArray may not have a full chunk of pairs.
if (ii + chunk < n)
{
copy(numAndIndexVector.begin()+ii, numAndIndexVector.begin()+ii+chunk, sortedArray.begin());
sort(sortedArray.begin(), sortedArray.end());
}
else
{
sortedArray = vector<pair<int, int>>(n - ii);
copy(numAndIndexVector.begin()+ii, numAndIndexVector.end(), sortedArray.begin());
sort(sortedArray.begin(), sortedArray.end());
}
// Testing a pair means checking to see if there is a value in the chunk within valueDiff. The pairs are
// sorted by value. So check adjacent values. But it may be the case that adjacent values in sortedArray are
// not within the indexDiff. In that case move out from the testing pair until a pair is found that is
// within indexDiff and then see if it is within the valueDiff. If a pair is found that is within indexDiff and
// not within valueDiff then going out farther will not produce a pair that is within valueDiff because
// pairs are sorted by value.
for(int jj=0; jj<sortedArray.size(); ++jj)
{
int kk = jj+1;
while((kk < sortedArray.size()) && (abs(sortedArray[jj].second - sortedArray[kk].second) > indexDiff))
{
++kk;
}
if((kk <sortedArray.size()) && ((sortedArray[kk].first - sortedArray[jj].first) <= valueDiff))
{
return true;
}
}
}
return false;
}
};