leetcode 1040. Steine verschieben bis durchgehend II

Link zum Originaltitel: Likou

Auf einem  unendlich  langen Zahlenstrahl  i ist die Position des ersten Kieselsteins  stones[i]. Wenn ein Kiesel die kleinste/maximale Position hat, dann wird der Kiesel  als Endpunkt-Kiesel  bezeichnet .

In jeder Runde kannst du einen Endstein aufnehmen und auf eine unbesetzte Position bewegen, wodurch der Stein kein Endstein mehr ist.

Es ist erwähnenswert, dass  stones = [1,2,5] Sie, wenn der Kiesel so ist,  den Endpunkt-Kiesel nicht auf Position 5 verschieben können  , denn egal auf welche Position Sie ihn verschieben (z. B. 0 oder 3), der Kiesel ist immer noch der Endpunkt Kiesel.

Wenn Sie keine Züge machen können, das heißt, wenn die Positionen dieser Steine ​​​​kontinuierlich sind, ist das Spiel vorbei.

Was ist die minimale und maximale Anzahl an Zügen, die Sie machen können, um das Spiel zu beenden? Gibt die Antwort als Array der Länge 2 zurück: answer = [minimum_moves, maximum_moves] .

Beispiel 1:

Eingabe: [7,4,9]
 Ausgabe: [1,2]
 Erklärung:
Wir können einmal ziehen, 4 -> 8, Spiel vorbei.
Alternativ können wir zweimal 9 -> 5, 4 -> 6 ziehen und das Spiel ist vorbei.

Beispiel 2:

Eingabe: [6,5,4,3,10]
 Ausgabe: [2,3]
 Erklärung:
Wir können 3 -> 8 ziehen, gefolgt von 10 -> 7, das Spiel ist vorbei.
Alternativ können wir 3 -> 7, 4 -> 8, 5 -> 9 bewegen, das Spiel ist vorbei.
Beachten Sie, dass wir keinen Zug wie 10 -> 2 machen können, um das Spiel zu beenden, da dies ein unerwünschter Zug ist.

Beispiel 3:

Eingabe: [100,101,104,102,103]
 Ausgabe: [0,0]

Kommentierte Version der Lösung:

class Solution {
public:
    vector<int> numMovesStonesII(vector<int>& stones) {
        // 获取石头数量
        int n = stones.size();
        // 将石头按位置排序
        sort(stones.begin(), stones.end());
        // 如果石头形成一个连续的序列,那么不需要移动就可以完成游戏,返回结果{0,0}
        if (stones.back() - stones[0] + 1 == n) {
            return {0, 0};
        }
        // 找到移动石头的最大值和最小值
        // 移动最大值就是将一侧的所有石头移动到另一侧,其中不需要移动的石头数量为 n - 1
        // 因此,最大值是两侧剩余石头数量的较大值减去需要移动的石头数量 n - 1
        int ma = max(stones[n - 2] - stones[0] + 1, stones[n - 1] - stones[1] + 1) - (n - 1);
        // 移动最小值就是将剩余的石头尽可能地靠拢,形成最大的连续序列
        int mi = n;
        // 遍历石头,找到最长的连续子序列
        for (int i = 0, j = 0; i < n && j + 1 < n; ++i) {
            // 在当前位置 i 的情况下,找到最远的 j,使得区间 [i,j] 中的石头可以放到一起,形成连续的子序列
            while (j + 1 < n && stones[j + 1] - stones[i] + 1 <= n) {
                ++j;
            }
            // 如果当前连续子序列的长度等于 n - 1,且两端的石头分别与序列的首尾相邻,那么只需要移动 2 个石头就可以形成连续的序列
            if (j - i + 1 == n - 1 && stones[j] - stones[i] + 1 == n - 1) {
                mi = min(mi, 2);
            } else {
                // 否则,需要移动 n - (j - i + 1) 个石头才能形成连续的序列
                mi = min(mi, n - (j - i + 1));
            }
        }
        // 返回最小值和最大值
        return {mi, ma};
    }
};

Supongo que te gusta

Origin blog.csdn.net/qq_40016005/article/details/130007548
Recomendado
Clasificación