Leetcode 第 140 场双周赛题解

Leetcode 第 140 场双周赛题解

  • [Leetcode 第 140 场双周赛题解](#Leetcode 第 140 场双周赛题解)
    • [题目1:3300. 替换为数位和以后的最小元素](#题目1:3300. 替换为数位和以后的最小元素)
    • [题目2:3301. 高度互不相同的最大塔高和](#题目2:3301. 高度互不相同的最大塔高和)
    • [题目3:3302. 字典序最小的合法序列](#题目3:3302. 字典序最小的合法序列)
    • [题目4:3303. 第一个几乎相等子字符串的下标](#题目4:3303. 第一个几乎相等子字符串的下标)

Leetcode 第 140 场双周赛题解

题目1:3300. 替换为数位和以后的最小元素

思路

遍历,维护数位之和的最小值。

代码

cpp 复制代码
class Solution {
public:
    int minElement(vector<int>& nums) {
        int minElem = INT_MAX;
        for (int &num : nums)
            minElem = min(minElem, digitSum(num));
        return minElem;
    }
    // 辅函数 - 求数位之和
    int digitSum(int x)
    {
        int sum = 0;
        while (x) {
            sum += x % 10;
            x /= 10;
        }
        return sum;
    }
};

复杂度分析

时间复杂度:O(nlogU),其中 n 是数组 nums 的长度,U=max(nums)。

空间复杂度:O(1)。

题目2:3301. 高度互不相同的最大塔高和

思路

将数组 maximumHeight 从大到小排序。

使用一个变量 mx 表示当前能用的最大高度,初始化为 maximumHeight[0]。

遍历数组 maximumHeight,如果 maximumHeight[i] >= mx,基于贪心的思想,maximumHeight[i] 最多保留到 mx - 1,更新 mx = maximumHeight[i]。

因为题目要求 maximumHeight[i] 要是一个正整数,所以如果 mx <= 0,可以提前得知没有合法的设置,返回 -1。

代码

cpp 复制代码
/*
 * @lc app=leetcode.cn id=3301 lang=cpp
 *
 * [3301] 高度互不相同的最大塔高和
 */

// @lc code=start
class Solution
{
public:
    long long maximumTotalSum(vector<int> &maximumHeight)
    {
        sort(maximumHeight.begin(), maximumHeight.end(), greater<>());
        int mx = maximumHeight[0];
        for (int i = 1; i < maximumHeight.size(); i++)
        {
            if (maximumHeight[i] >= mx)
                maximumHeight[i] = mx - 1;
            mx = maximumHeight[i];
            if (mx <= 0)
                return -1;
        }
        return accumulate(maximumHeight.begin(), maximumHeight.end(), 0LL);
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n),其中 n 是数组 maximumHeight 的长度。

空间复杂度:O(1)。

题目3:3302. 字典序最小的合法序列

思路

题解:https://leetcode.cn/problems/find-the-lexicographically-smallest-valid-sequence/solutions/2934051/qian-hou-zhui-fen-jie-zi-xu-lie-pi-pei-t-le8d/

代码

cpp 复制代码
/*
 * @lc app=leetcode.cn id=3302 lang=cpp
 *
 * [3302] 字典序最小的合法序列
 */

// @lc code=start
class Solution
{
public:
    vector<int> validSequence(string word1, string word2)
    {
        int n = word1.length(), m = word2.length();
        vector<int> suf(n + 1);
        suf[n] = m;
        for (int i = n - 1, j = m - 1; i >= 0; i--)
        {
            if (j >= 0 && word1[i] == word2[j])
                j--;
            suf[i] = j + 1;
        }

        vector<int> ans(m);
        bool changed = false; // 是否修改过
        for (int i = 0, j = 0; i < n; i++)
        {
            if (word1[i] == word2[j] || !changed && suf[i + 1] <= j + 1)
            {
                if (word1[i] != word2[j])
                    changed = true;
                ans[j++] = i;
                if (j == m)
                    return ans;
            }
        }
        return {};
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n),其中 n 是 word1 的长度。

空间复杂度:O(n),其中 n 是 word1 的长度。

题目4:3303. 第一个几乎相等子字符串的下标

思路

现在变成了两个问题:

第一个问题:对于每个从 s[i] 开始的字符串 s[i...],计算它能匹配 pattern 多长的前缀。

第二个问题:对于每个以 s[j] 结尾的字符串 s[...j],计算它能匹配 pattern 多长的后缀。

代码

cpp 复制代码
/*
 * @lc app=leetcode.cn id=3303 lang=cpp
 *
 * [3303] 第一个几乎相等子字符串的下标
 */

// @lc code=start
class Solution
{
public:
    int minStartingIndex(string s, string pattern)
    {
        int n = s.length(), m = pattern.length();
        string rev_s = string(s.rbegin(), s.rend());
        string rev_pattern = string(pattern.rbegin(), pattern.rend());
        vector<int> preZ = getZ(pattern + s);
        vector<int> sufZ = getZ(rev_pattern + rev_s);
        reverse(sufZ.begin(), sufZ.end());
        for (int i = 0; i <= n - m; i++)
            if (preZ[i + m] + sufZ[i + m - 1] >= m - 1)
                return i;
        return -1;
    }
    // 辅函数
    vector<int> getZ(string s)
    {
        int n = s.length();
        vector<int> z(n);
        int box_l = 0, box_r = 0; // z-box 左右边界
        for (int i = 1; i < n; i++)
        {
            if (i <= box_r)
                z[i] = min(z[i - box_l], box_r - i + 1);
            while (i + z[i] < n && s[z[i]] == s[i + z[i]])
            {
                box_l = i;
                box_r = i + z[i];
                z[i]++;
            }
        }
        return z;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n+m),其中 n 是字符串 s 的长度,m 是字符串 pattern 的长度。

空间复杂度:O(n+m),其中 n 是字符串 s 的长度,m 是字符串 pattern 的长度。

相关推荐
娅娅梨6 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
DdddJMs__1359 分钟前
C语言 | Leetcode C语言题解之第557题反转字符串中的单词III
c语言·leetcode·题解
兵哥工控10 分钟前
MFC工控项目实例二十九主对话框调用子对话框设定参数值
c++·mfc
我爱工作&工作love我18 分钟前
1435:【例题3】曲线 一本通 代替三分
c++·算法
娃娃丢没有坏心思1 小时前
C++20 概念与约束(2)—— 初识概念与约束
c语言·c++·现代c++
lexusv8ls600h1 小时前
探索 C++20:C++ 的新纪元
c++·c++20
lexusv8ls600h1 小时前
C++20 中最优雅的那个小特性 - Ranges
c++·c++20
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
Sunyanhui11 小时前
力扣 二叉树的直径-543
算法·leetcode·职场和发展