LeetCode 力扣周赛 272

205 阅读2分钟

排名跌出一千咯~

前三题都挺简单的,第四题真的没想到,赛后一看题解,😯,真妙啊~ 为啥自己就想不到🤦‍♂️

5956. 找出数组中的第一个回文字符串

思路:暴力枚举

时间复杂度O(words)O(\sum|words|)

空间复杂度O(1)O(1)

题目比较简单,没啥优化的空间了,直接暴力检查每个字符串就好啦。

class Solution {
public:
    string firstPalindrome(vector<string>& words) {
        // 枚举字符串
        for (const auto &w : words) {
            int  i = 0, n = w.size();
            // 检查当前字符串是否回文
            for (; i < n/2 && w[i] == w[n-i-1]; i++) {}
            if (i == n/2) {
                return w;
            }
        }
        return "";
    }
};

5957. 向字符串添加空格

思路:模拟

时间复杂度O(s+spaces)O(|s| + |spaces|)

空间复杂度O(s+spaces)O(|s| + |spaces|)

没有啥弯弯绕,直接按题目要求模拟即可。

class Solution {
public:
    string addSpaces(string s, vector<int>& spaces) {
        // anw 用于存储答案。
        string anw;
        // 遍历 s
        for (int i = 0, j = 0; i < s.size(); i++) {
            // 按题目要求检查,是否需要追加空格
            if (j < spaces.size() && i == spaces[j]) {
                anw += ' ';
                j++;
            }
            // 追加字符 s[i]
            anw += s[i];
        }
        return anw;
    }
};

5958. 股票平滑下跌阶段的数目

思路:递推

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

空间复杂度O(1)O(1)

设有一维数组 lenlenlenilen_i 表示以 ii 结尾的最长平滑下降区间的长度,则答案可表示为:

i=0n1leni\sum_{i=0}^{n-1}len_i

lenlen 也易求得:

  • 如果价格满足pi11=pip_{i-1} - 1 = p_{i},则 leni=leni1+1len_i = len_{i-1}+1
  • 反之 leni=1len_i = 1
class Solution {
public:
    long long getDescentPeriods(vector<int>& prices) {
        int pre = -1;
        int len = 0;
        int64_t anw = 0;
        for (auto cur : prices) {
            len = (cur == pre-1 ? len+1 : 1);
            pre = cur;
            anw += len;
        }
        return anw;
    }
};

5959. 使数组 K 递增的最少操作次数

思路:数组拆分,最长非降子序列。

时间复杂度O(nlgn)O(n*\lg n)

空间复杂度O(nk)O(\frac{n}{k})

KK 的限制,使得数组 arrarr 被分割为了 kk 个子序列,即:

  • 0,k,2k,3k,...0,k,2k,3k,...
  • 1,1+k,1+2k,1+3k,...1,1+k,1+2k,1+3k,...
  • 2,2+k,2+2k,2+3k,...2,2+k,2+2k,2+3k,...
  • ......
  • k1,2k1,3k1,k−1,2k−1,3k−1,…

kk 个子序列,可分别求出最少操作次数,求和即为答案。

对于每个子序列,最优的修改方案为:求出其最长非降子序列,然后修改子序列之外的值。

力扣官方给出一种解释是:未被修改的值,需满足单调递增。而需修改的值,因为可以修改为任意正整数,所以无需考虑。

因此,找出最多的无需修改的值(最长非降子序列),剩下的就是最小操作次数啦。

class Solution {
public:
    int kIncreasing(vector<int>& arr, int k) {
        int anw = 0;
        // 枚举以 i 开头的子序列
        for (int i = 0; i < k; i++) {
            // lis 用于求解最长非降子序列长度
            vector<int> lis;
            // cnt 用于记录以 i 开头的子序列的长度
            int cnt = 0;
            // 枚举当前子序列中的元素,二分求解最长非降子序列
            for (int j = i; j < arr.size(); j += k, cnt++) {
                auto it = upper_bound(lis.begin(), lis.end(), arr[j]);
                if (it == lis.end()) {
                    lis.emplace_back(arr[j]);
                } else {
                    *it = arr[j];
                }
            }
            // 累加答案
            anw += cnt - lis.size();
        }
        return anw;
    }
};