LeetCode 力扣周赛 276

147 阅读1分钟

周末给老婆过生日去啦,赛后补一把题~

2138. 将字符串拆分为若干长度为 k 的组

思路:模拟

时间复杂度O(n)O(n)

按照题意即可,就不赘述啦。

class Solution {
public:
    vector<string> divideString(string s, int k, char fill) {
        std::vector<std::string> anw;
        int i = 0;
        for (; i+k < s.size(); i += k) {
            anw.push_back(s.substr(i,k));
        }
        if (i != s.size()) {
            anw.push_back(s.substr(i));
            anw.back() += std::string(k-(s.size()-i), fill);
        }
        return anw;
    }
};

2139. 得到目标值的最少行动次数

思路:逆向模拟,贪心

时间复杂度O(maxDoubles)O(maxDoubles)

此题的关键在于让 maxDoublesmaxDoubles 次乘法发挥最大作用。

设最后一次使用乘法必然时值为 xx,则 xx 必然满足:

  • 2xtarget2*x\le target
  • 2(x+1)>target2*(x+1) > target

只有这样才能使最后一次乘法发挥最大作用。同理,设使用倒数第二次乘法时值为 xx',也必有:

  • 2xx2*x'\le x
  • 2(x+1)>x2*(x'+1) > x

依次类推。不难想到,将乘法转换为除法,将加法转换为减法更易找到这些临界值。

比如,x=target/2x = \lfloor target/2\rfloorx=x/2x'=\lfloor x/2\rfloor,依次类推。

class Solution {
public:
    int minMoves(int target, int maxDoubles) {
        int cnt = 0;
        while (target != 1) {
            // 能除则除
            if (--maxDoubles >= 0) {
                // (target&1):余数部分只能做减法了
                // 1:做一次除法
                cnt += (target&1) + 1;
                target /= 2;
                continue;
            }
            // 不能则减
            cnt += target - 1;
            target = 1;
        }
        return cnt;
    }
};

2140. 解决智力问题

思路:递推

时间复杂度O(n)O(n)

设有一维数组 scorescorescoreiscore_i 表示在题目 ii 可自由处理的前提下后 nin-i 道题的最高得分。对应题目的 ii 的策略,scoreiscore_i 有以下几种取值。

  • 做第 ii 道题,则 scorei=gaini+scorei+skipiscore_i = gain_i + score_{i+skip_i}
  • 不做第 ii 到题,则 scorei=scorei+1score_i = score_{i+1}

其中,gainigain_i 表示第 ii 到题的得分,skipiskip_i 表示做完 ii 题需跳过的数目。

class Solution {
public:
    long long mostPoints(vector<vector<int>>& questions) {
        vector<int64_t> score(questions.size(), 0);
        for (int i = questions.size()-1; i >= 0; i--) {
            int64_t gain = questions[i][0];
            int64_t skip = questions[i][1];
            if (i + skip + 1 < score.size()) {
                score[i] = max(score[i+1], gain + score[i+skip+1]);
            } else if (i + 1 < score.size()){
                score[i] = max(score[i+1], gain);
            } else {
                score[i] = gain;
            }
        }
        return score[0];
    }
};

2141. 同时运行 N 台电脑的最长时间

思路:二分

时间复杂度O(mlgc)O(m\lg c)mm 为电池数量,cc 为总电量。

假设最长能运行 xx 分钟,则运行 x1x-1x2x-2 分钟必然都有可行方案,因此可以二分答案。

那么问题变成了,对于给定的 xx,如何判断是否存在方案。

考虑给定的 xx,第 ii 节电池最多供电 max(x,batteriesi)max(x,batteries_i) 分钟。如果 (max(x,batteriesi))>nx\sum(max(x,batteries_i)) \gt n*x,则方案必然存在,反之则必然不存在。

class Solution {
public:
    long long maxRunTime(int n, vector<int>& batteries) {
        int64_t left = 0, right = 0;
        for (auto b : batteries) {
            right += b;
        }
        while (left <= right) {
            auto mid = (left + right) / 2;
            int64_t sum = 0;
            for (auto b : batteries) {
                sum += min(int64_t(b), mid);
            }
            if (sum >= n * mid) {
                left = mid + 1;
            }
            else {
                right = mid - 1;
            }
        }
        return left-1;
    }
};