Start learning free

LESSON 253 OF 348 · BINARY SEARCH

The Factory in Kotlin: Brute Force, One Time Unit at a Time

Practice O(n * k * T) Read the full explanation

There are N workers in a factory. Each worker packs the same type of product, and for each of them we know the time it takes them to pack one product.

Find out the minimum amount of time the workers need to pack at least K products.

Example:

Input: times = [4, 7, 3, 6, 7, 1], K = 60
Output:30
Explanation:
1st worker packs 7 products in 4 * 7 = 28 units of time
2nd worker packs 4 products in 7 * 4 = 28 units of time
3rd worker packs 10 products in 3 * 10 = 30 units of time
4th worker packs 5 products in 6 * 5 = 30 units of time
5th worker packs 4 products in 7 * 4 = 28 units of time
6th worker packs 30 products in 1 * 30 = 30 units of time
We have 7 + 4 + 10 + 5 + 4 + 30 = 60 total products
in max(28, 28, 30, 30, 28, 30) = 30 units of time
and this is the minimum amount of time
since in 29 units of time we can pack only
7 + 4 + 9 + 4 + 4 + 29 = 57 products

Note:

Your algorithm should run in O(n * k * T) time and use O(1) extra space.


STEP 1 OF 9
    Ctrl + Enter to check

    KOTLIN · BINARY SEARCH

    The Factory in Kotlin, explained

    Problem overview

    The function minTime receives an IntArray called times and an Int called K. Worker i needs times[i] units of time to pack one product. All workers pack at once, each at their own pace. The function returns the smallest amount of time after which the workers have packed at least K products in total.

    For times = [4, 7, 3, 6, 7, 1] and K = 60 the answer is 30. In 30 units the workers pack 7, 4, 10, 5, 4 and 30 products, which is exactly 60. In 29 units they pack 7 + 4 + 9 + 4 + 4 + 29 = 57, which is not enough.

    A worker who needs t units per product packs time / t products in time units, rounded down, because an unfinished product doesn't count.

    Approach: try each time in turn

    This lesson is the plain version. Start at time 0 and ask "how many products can the workers pack in this much time?". If the answer is still below K, add one unit and ask again. The first time that reaches K is the minimum.

    This works because the total can never shrink as time grows: every worker's count either stays the same or goes up. The first time at which the total reaches K is therefore the smallest time at which it is at least K, and all later times also qualify.

    The cost is high. Every candidate time costs a pass over all n workers, and the number of candidates can be as large as the answer itself. With one worker who needs 1000 units per product and K = 1000000, the loop tests a billion different times. The statement writes the budget as O(n * k * T), which signals that this is the slow, brute-force baseline. A later lesson on the same problem replaces the one-unit steps with a binary search on the answer.

    Step by step

    1. Declare time with var and start it at 0. It changes every iteration, so val would not compile.
    2. Loop while the workers are short. The helper countProducts(times, time) returns how many products everyone packs in time units. The loop runs while that count is less than K.
    3. Add one unit of time with time++ in the loop body.
    4. Return time when the loop stops. It is the first time at which the count reached K.
    5. Write the helper above minTime as fun countProducts(times: IntArray, time: Int): Int.
    6. Start a var products at 0 to hold the running total.
    7. Loop over the workers with for (t in times), where t is one worker's time per product.
    8. Add time / t to products. Dividing two Ints already drops the fraction, which is the rounding down the problem needs.
    9. Return products after the loop.

    The solution in Kotlin

    class Solution {
        fun countProducts(times: IntArray, time: Int): Int {
            var products = 0
            for (t in times) {
                products += time / t
            }
            return products
        }
        fun minTime(times: IntArray, K: Int): Int {
            var time = 0
            while (countProducts(times, time) < K) {
                time++
            }
            return time
        }
    }
    

    The Kotlin details worth a closer look:

    • for (t in times). This loops over the values of the array directly, with no index. Use times.indices only when the position matters.
    • Integer division. For two Ints, / truncates, so 29 / 4 is 7 and 29 / 7 is 4. If you want a fractional result you have to convert one side to Double.
    • products += .... Compound assignment is allowed on a var. Writing it on a val is a compile error.
    • time++ as a statement. Kotlin has the increment operator for variables. It is a statement here, not a value you need to use.
    • A capital parameter name. K is a legal parameter name; Kotlin style prefers lowercase, but the lesson keeps the name from the statement.

    Complexity

    Time: proportional to the answer times n. Each call to countProducts is O(n), and the loop makes one call per candidate time from 0 up to the answer, which is at most min(times) * K. In the worst case that is O(n * K * T) with T the smallest time, matching the statement's budget. It is fine for small inputs and far too slow when K or the times are large.

    Space: O(1). The code keeps a few Ints.

    Edge cases and common mistakes

    • K = 0. At time 0 the count is already 0, which is not below 0, so the loop doesn't run and the answer is 0.
    • Dividing the wrong way. The number of products is time / t, not t / time. A worker with a slow t packs few products.
    • Counting partial products. A worker with t = 7 has packed 4 products at time 29 and 4 products at time 30. The fifth product only counts at time 35.
    • Starting at time 1. Starting at 0 handles K = 0 without a special case.
    • Returning products instead of time. The function returns the time, not the product count.
    • Division by zero. A time of 0 per product would throw ArithmeticException in time / t. The problem assumes every time is positive.

    Testing

    • times = [4, 7, 3, 6, 7, 1], K = 60 gives 30. countProducts for time 29 gives 57.
    • times = [5], K = 3 gives 15.
    • times = [2, 3], K = 5 gives 6.
    • times = [4, 7, 3, 6, 7, 1], K = 0 gives 0.
    Keep going with KotlinAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free