/**
* Utility methods for finding distances between values in arrays.
*/
class ArrayDistance {
/**
* Finds the minimum distance between two target values in an array.
*
* Example:
* [2, 3, 7, 3, 3, 4, 8, 8, 8, 11, 9, 1, 3]
*
* Targets:
* 3 and 8
*
* Result:
* 2
*
* @param {number[]} numbers - The input array.
* @param {number} target1 - The first target value.
* @param {number} target2 - The second target value.
* @returns {number}
* Returns the minimum distance between the targets,
* or -1 if no valid pair exists.
* @throws {TypeError} If numbers is not an array.
*/
static findMinimumDistance(numbers, target1, target2) {
if (!Array.isArray(numbers)) {
throw new TypeError("numbers must be an array.");
}
// Special case: both targets are the same value.
if (target1 === target2) {
return this.findMinimumDistanceBetweenDuplicates(
numbers,
target1
);
}
let lastSeenIndex = -1;
let minimumDistance = Number.MAX_SAFE_INTEGER;
for (let currentIndex = 0; currentIndex < numbers.length; currentIndex++) {
const currentValue = numbers[currentIndex];
// Ignore values that are not relevant.
if (currentValue !== target1 && currentValue !== target2) {
continue;
}
/*
* If we've previously seen one target value and
* the current value is the other target value,
* update the minimum distance.
*/
if (
lastSeenIndex >= 0 &&
currentValue !== numbers[lastSeenIndex]
) {
const distance = currentIndex - lastSeenIndex;
minimumDistance = Math.min(
minimumDistance,
distance
);
}
// Store the most recent occurrence.
lastSeenIndex = currentIndex;
}
return minimumDistance === Number.MAX_SAFE_INTEGER
? -1
: minimumDistance;
}
/**
* Finds the minimum distance between consecutive occurrences
* of the same value.
*
* @param {number[]} numbers - The input array.
* @param {number} target - The target value.
* @returns {number}
* Returns the minimum distance or -1 if the value appears
* fewer than two times.
*/
static findMinimumDistanceBetweenDuplicates(numbers, target) {
let previousIndex = -1;
let minimumDistance = Number.MAX_SAFE_INTEGER;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] !== target) {
continue;
}
if (previousIndex >= 0) {
const distance = i - previousIndex;
minimumDistance = Math.min(
minimumDistance,
distance
);
}
previousIndex = i;
}
return minimumDistance === Number.MAX_SAFE_INTEGER
? -1
: minimumDistance;
}
}
/*
* Example usage
*/
const numbers = [2, 3, 7, 3, 3, 4, 8, 8, 8, 11, 9, 1, 3];
const result = ArrayDistance.findMinimumDistance(numbers, 3, 8);
console.log(
result >= 0
? `Minimum distance between 3 and 8: ${result}`
: "No valid pair found."
);
/*
run:
Minimum distance between 3 and 8: 2
*/