LeetCode Entry

2594. Minimum Time to Repair Cars

16.03.2025 medium 2025 kotlin rust

Min rank[i] count^2 to fix all cars search

2594. Minimum Time to Repair Cars medium blog post substack youtube 1.webp

Join me on Telegram

https://t.me/leetcode_daily_unstoppable/929

Problem TLDR

Min rank[i] * count^2 to fix all cars #medium #binary_search #heap

Intuition

Didn’t solve without a hint. My (wrong) intuition was to spread the work evenly except the lowest rank:


    // DP 10^5 * 100 TLE ?
    //
    // 1 2 3 4      10
    // 1*a^2 + 2*b^2 + 3*c^2 + 4*d^2
    //   7       1       1       1  max(4*1*1, 1*7*7) 49
    //   4       2       2       2  max(4*2*2, 1*4*4) 16
    //   3       3       2       2    ? 2*3*3 > 4*2*2
    //   1       3       3       3  max(4*3*3, 1*1*1) 36
    //
    // 49 > 16 < 36     search in a parabolic space
    //
    //

    // 1 5 8      6
    // 6 0 0
    // 4 1 1
    // 2 2 2   1*2*2 5*2*2  8*2*2
    // 0 3 3

However, that didn’t allow for the binary search as space is parabolic, and optimal is not a guarantee.

The hint: set the max allowed time

    // hint: cnt * cnt * r = time

Now, we can check how many cars each rank fixes: sqrt(r/time).

Another solution is a heap from u/lee215/:

  • lets give each worker a single car to fix
  • compute the time as rank * 1 * 1 = rank
  • take workers one by one over increasing time
  • this gives TLE, so put workers in the buckets by ranks, now we can move time much faster freq[rank] * rank * 1 * 1
  • do this until all cars fixed, the time is the current time

Approach

  • computing the frequency of the ranks also speed up the binary search (Rust solution)

Complexity

  • Time complexity: \(O(nlog(m))\) or O(n + 100log(m)), or O(n + cars*log(100)) for heap

  • Space complexity: \(O(1)\), or O(100) for heap and frequency-optimized binary search

Code


    fun repairCars(ranks: IntArray, cars: Int): Long {
        var lo = 0L; var hi = Long.MAX_VALUE
        while (lo <= hi) {
            val time = lo + (hi - lo) / 2L
            val cnt = ranks.sumOf { Math.sqrt(1.0 * time / it).toLong() }
            if (cnt < cars) lo = time + 1 else hi = time - 1
        }
        return lo
    }


    fun repairCars(ranks: IntArray, cars: Int): Long {
        val q = PriorityQueue<List<Int>>(compareBy { (r, c) -> 1L * r * c * c })
        val f = IntArray(101); for (r in ranks) ++f[r]; var cnt = 0; var t = 0L
        for (r in 1..100) if (f[r] > 0) q += listOf(r, 1)
        while (cnt < cars) {
            val (r, c) = q.poll(); q += listOf(r, c + 1)
            cnt += f[r]; t = 1L * r * c * c;
        }
        return t
    }


    pub fn repair_cars(ranks: Vec<i32>, cars: i32) -> i64 {
        let (mut f, mut lo, mut hi, c) = (vec![0; 101], 0, i64::MAX, cars as i64);
        for r in ranks { f[r as usize] += 1; hi = hi.min(r as i64 * c * c) }
        while lo <= hi {
            let (time, mut cnt) = (lo + (hi - lo) / 2, 0);
            for r in 1..101 { cnt += f[r] * (((time / r as i64) as f64).sqrt() as i64) }
            if cnt < c { lo = time + 1 } else { hi = time - 1 }
        } lo
    }


    long long repairCars(vector<int>& ranks, int c) {
        long long lo = 1, hi = 100'000'000'000'000LL, f[101] = {0};
        for (int r: ranks) ++f[r], hi = min(hi, 1LL * r * c * c);
        while (lo <= hi) {
            long long t = lo + (hi - lo) / 2, cnt = 0;
            for (int r = 1; r < 101; ++r) cnt += f[r] * int(sqrt(t / r));
            cnt < c ? lo = t + 1 : hi = t - 1;
        } return lo;
    }