How to find the minimum distance between two numbers in an array with Swift

1 Answer

0 votes
import Foundation

/// Utility type for finding distances between values in collections.
enum ArrayDistance {

    /// Finds the minimum distance between two target values in an array.
    ///
    /// - Parameters:
    ///   - numbers: The array to search.
    ///   - target1: The first target value.
    ///   - target2: The second target value.
    ///
    /// - Returns:
    ///   The minimum distance between the target values,
    ///   or `nil` if no valid pair exists.
    ///
    /// - Complexity:
    ///   - Time: O(n)
    ///   - Space: O(1)
    static func findMinimumDistance(
        in numbers: [Int],
        between target1: Int,
        and target2: Int
    ) -> Int? {

        // Special case: both targets are the same value.
        if target1 == target2 {
            return findMinimumDistanceBetweenDuplicates(
                in: numbers,
                target: target1
            )
        }

        var lastSeenIndex: Int?
        var minimumDistance: Int?

        for (currentIndex, currentValue) in numbers.enumerated() {

            // Ignore values that are not targets.
            guard currentValue == target1 || currentValue == target2 else {
                continue
            }

            /*
             If we previously encountered one target
             and the current value is the other target,
             update the minimum distance.
             */
            if let previousIndex = lastSeenIndex,
               currentValue != numbers[previousIndex] {

                let distance = currentIndex - previousIndex

                minimumDistance = minimumDistance.map {
                    min($0, distance)
                } ?? distance
            }

            // Remember the most recent occurrence.
            lastSeenIndex = currentIndex
        }

        return minimumDistance
    }

    /// Finds the minimum distance between consecutive occurrences
    /// of the same value.
    ///
    /// - Parameters:
    ///   - numbers: The array to search.
    ///   - target: The target value.
    ///
    /// - Returns:
    ///   The minimum distance between occurrences,
    ///   or `nil` if fewer than two occurrences exist.
    private static func findMinimumDistanceBetweenDuplicates(
        in numbers: [Int],
        target: Int
    ) -> Int? {

        var previousIndex: Int?
        var minimumDistance: Int?

        for (currentIndex, currentValue) in numbers.enumerated() {

            guard currentValue == target else {
                continue
            }

            if let previous = previousIndex {

                let distance = currentIndex - previous

                minimumDistance = minimumDistance.map {
                    min($0, distance)
                } ?? distance
            }

            previousIndex = currentIndex
        }

        return minimumDistance
    }
}

// Example Usage

let numbers = [2, 3, 7, 3, 3, 4, 8, 8, 8, 11, 9, 1, 3]

if let distance = ArrayDistance.findMinimumDistance(
    in: numbers,
    between: 3,
    and: 8
) {
    print("Minimum distance between 3 and 8: \(distance)")
} else {
    print("No valid pair found.")
}


/*
run:

Minimum distance between 3 and 8: 2

*/

 



answered Oct 22 by avibootz

Related questions

...