LeetCode-in-Java

3376. Minimum Time to Break Locks I

Medium

Bob is stuck in a dungeon and must break n locks, each requiring some amount of energy to break. The required energy for each lock is stored in an array called strength where strength[i] indicates the energy needed to break the ith lock.

To break a lock, Bob uses a sword with the following characteristics:

Your task is to determine the minimum time in minutes required for Bob to break all n locks and escape the dungeon.

Return the minimum time required for Bob to break all n locks.

Example 1:

Input: strength = [3,4,1], K = 1

Output: 4

Explanation:

Time Energy X Action Updated X
0 0 1 Nothing 1
1 1 1 Break 3rd Lock 2
2 2 2 Nothing 2
3 4 2 Break 2nd Lock 3
4 3 3 Break 1st Lock 3

The locks cannot be broken in less than 4 minutes; thus, the answer is 4.

Example 2:

Input: strength = [2,5,4], K = 2

Output: 5

Explanation:

Time Energy X Action Updated X
0 0 1 Nothing 1
1 1 1 Nothing 1
2 2 1 Break 1st Lock 3
3 3 3 Nothing 3
4 6 3 Break 2nd Lock 5
5 5 5 Break 3rd Lock 7

The locks cannot be broken in less than 5 minutes; thus, the answer is 5.

Constraints:

Solution

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Solution {
    public int findMinimumTime(List<Integer> strength, int k) {
        List<Integer> strengthLocal = new ArrayList<>(strength);
        Collections.sort(strengthLocal);
        int res = strengthLocal.get(0);
        strengthLocal.remove(0);
        int x = 1;
        while (!strengthLocal.isEmpty()) {
            x += k;
            int nextTime = (strengthLocal.get(0) - 1) / x + 1;
            int canBreak = nextTime * x;
            int indexRemove = findIndex(strengthLocal, canBreak);
            if (strengthLocal.size() > 1) {
                int nextTime1 = (strengthLocal.get(1) - 1) / x + 1;
                int canBreak1 = nextTime1 * x;
                int indexRemove1 = findIndex(strengthLocal, canBreak1);
                if (nextTime1 + (strengthLocal.get(0) - 1) / (x + k)
                        < nextTime + (strengthLocal.get(1) - 1) / (x + k)) {
                    nextTime = nextTime1;
                    indexRemove = indexRemove1;
                }
            }
            res += nextTime;
            strengthLocal.remove(indexRemove);
        }
        return res;
    }

    private int findIndex(List<Integer> strength, int canBreak) {
        int l = 0;
        int r = strength.size() - 1;
        int res = -1;
        while (l <= r) {
            int mid = (l + r) / 2;
            if (strength.get(mid) <= canBreak) {
                res = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        return res;
    }
}