/**
* Utility class for finding distances between values in arrays.
*/
class ArrayDistance {
/**
* Prevent instantiation.
*/
private constructor() {}
/**
* Finds the minimum distance between two target values in an array.
*
* @param numbers Array to search.
* @param target1 First target value.
* @param target2 Second target value.
* @returns The minimum distance between the targets,
* or -1 if no valid pair exists.
* @throws TypeError If numbers is not an array.
*/
public static findMinimumDistance(
numbers: readonly number[],
target1: number,
target2: number
): number {
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: number = -1;
let minimumDistance: number = Number.MAX_SAFE_INTEGER;
for (
let currentIndex: number = 0;
currentIndex < numbers.length;
currentIndex++
) {
const currentValue: number = numbers[currentIndex];
// Skip values that are not targets.
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: number =
currentIndex - lastSeenIndex;
minimumDistance = Math.min(
minimumDistance,
distance
);
}
// Remember 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 numbers Array to search.
* @param target Value to search for.
* @returns The minimum distance between occurrences,
* or -1 if fewer than two occurrences exist.
*/
private static findMinimumDistanceBetweenDuplicates(
numbers: readonly number[],
target: number
): number {
let previousIndex: number = -1;
let minimumDistance: number = Number.MAX_SAFE_INTEGER;
for (let i: number = 0; i < numbers.length; i++) {
if (numbers[i] !== target) {
continue;
}
if (previousIndex >= 0) {
const distance: number = i - previousIndex;
minimumDistance = Math.min(
minimumDistance,
distance
);
}
previousIndex = i;
}
return minimumDistance === Number.MAX_SAFE_INTEGER
? -1
: minimumDistance;
}
}
// Example usage
const numbers: number[] = [2, 3, 7, 3, 3, 4, 8, 8, 8, 11, 9, 1, 3];
const result: number = 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
*/