Leetcode 第 383 场周赛题解

本文解析了LeetCode第383场周赛中的四道题目,涉及边界上的蚂蚁计数、单词恢复所需最短时间内删除操作、网格区域平均强度计算以及字符串恢复时间II的Z函数算法。详细介绍了每个问题的解题思路、代码实现及复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode 第 383 场周赛题解

题目1:3028. 边界上的蚂蚁

思路

遍历下标 i,1<=i<=nums.length(),返回 accumulate(nums.begin(), nums.begin() + i, 0) = 0 的次数。

代码

class Solution
{
public:
    int returnToBoundaryCount(vector<int> &nums)
    {
        int count = 0;
        int sum = 0;
        for (int &num : nums)
        {
            sum += num;
            if (!sum)
                count++;
        }
        return count;
    }
};

复杂度分析

时间复杂度:O(n)。

空间复杂度:O(1)。

题目2:3029. 将单词恢复初始状态所需的最短时间 I

思路

暴力。

不断删除前 k 个字符,一旦发现此时删除后的字符串和原字符串的前缀相等,那么就不需要再删除了,因为后续的添加的字符是可以任意指定的。

举个例子,对于示例 1,abacaba,k=3:

  1. 第一次删除:变成 caba###,#表示可以添加的任意字符,此时删除后的字符串是 caba,没有与原字符串中任意字符串匹配;
  2. 第二次删除:变成 a######,此时删除后的字符串是 a,与原字符串的前缀 a 匹配成功,那么后续就不用再删了,因为后面的 # 是可以改为任意字符的,所以可以恢复到初始状态。

代码

/*
 * @lc app=leetcode.cn id=3029 lang=cpp
 *
 * [3029] 将单词恢复初始状态所需的最短时间 I
 */

// @lc code=start

// 暴力

class Solution
{
public:
    int minimumTimeToInitialState(string word, int k)
    {
        int n = word.size();
        int time = 0;
        for (int i = 0; i < n; i += k)
        {
            time++;
            if (i + k < n)
            {
                string temp = word.substr(i + k);

                if (word.substr(0, temp.size()) == temp)
                    break;
            }
        }
        return time;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n),n 是字符串 s 的长度。

空间复杂度:O(1)。

题目3:3030. 找出网格的区域平均强度

思路

模拟。

在这里插入图片描述

代码

/*
 * @lc app=leetcode.cn id=3030 lang=cpp
 *
 * [3030] 找出网格的区域平均强度
 */

// @lc code=start

// 模拟

class Solution
{
public:
    vector<vector<int>> resultGrid(vector<vector<int>> &image, int threshold)
    {
        int m = image.size(), n = m ? image[0].size() : 0;
        vector<vector<int>> result(m, vector<int>(n));
        vector<vector<int>> cnt(m, vector<int>(n));

        for (int i = 2; i < m; i++)
        {
            for (int j = 2; j < n; j++)
            {
                // 检查左右相邻格子
                bool ok = true;
                for (int x = i - 2; x <= i; x++)
                {
                    if (abs(image[x][j - 2] - image[x][j - 1]) > threshold ||
                        abs(image[x][j - 1] - image[x][j]) > threshold)
                    {
                        ok = false;
                        break; // 不合法,下一个
                    }
                }
                if (!ok)
                    continue;

                // 检查上下相邻格子
                for (int y = j - 2; y <= j; y++)
                {
                    if (abs(image[i - 2][y] - image[i - 1][y]) > threshold ||
                        abs(image[i - 1][y] - image[i][y]) > threshold)
                    {
                        ok = false;
                        break; // 不合法,下一个
                    }
                }
                if (!ok)
                    continue;

                // 合法,计算 3x3 子网格的平均值
                int avg = 0;
                for (int x = i - 2; x <= i; x++)
                    for (int y = j - 2; y <= j; y++)
                        avg += image[x][y];
                avg /= 9;

                // 更新 3x3 子网格内的 result
                for (int x = i - 2; x <= i; x++)
                    for (int y = j - 2; y <= j; y++)
                    {
                        result[x][y] += avg; // 先累加,最后再求平均值
                        cnt[x][y]++;
                    }
            }
        }

        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
            {
                if (cnt[i][j] == 0)
                {
                    // (i,j) 不属于任何子网格
                    result[i][j] = image[i][j];
                }
                else
                {
                    // 求平均值
                    result[i][j] /= cnt[i][j];
                }
            }
        return result;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(Amn),其中 m 和 n 分别为矩阵 image 的行数和列数,A=9 表示子网格大小。

空间复杂度:O(mn),其中 m 和 n 分别为矩阵 image 的行数和列数。

题目4:3031. 将单词恢复初始状态所需的最短时间 II

思路

题解:【视频讲解】Z 函数(扩展 KMP)

代码

/*
 * @lc app=leetcode.cn id=3031 lang=cpp
 *
 * [3031] 将单词恢复初始状态所需的最短时间 II
 */

// @lc code=start

// 暴力

// class Solution
// {
// public:
//     int minimumTimeToInitialState(string word, int k)
//     {
//         string_view s = word; // 内存不溢出和不超时的关键
//         int n = s.size();
//         for (int t = 1, i = k; true; t++, i += k)
//             if (i >= n || s.substr(i) == s.substr(0, n - i))
//                 return t;
//         return -1;
//     }
// };

// Z 函数算法(拓展 KMP)

class Solution
{
public:
    int minimumTimeToInitialState(string s, int k)
    {
        int n = s.size();
        vector<int> z(n);
        int l = 0, r = 0;
        for (int i = 1; i < n; i++)
        {
            if (i <= r)
            {
                z[i] = min(z[i - l], r - i + 1);
            }
            while (i + z[i] < n && s[z[i]] == s[i + z[i]])
            {
                l = i;
                r = i + z[i];
                z[i]++;
            }
            if (i % k == 0 && z[i] >= n - i)
            {
                return i / k;
            }
        }
        return (n - 1) / k + 1;
    }
};
// @lc code=end

复杂度分析

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

空间复杂度:O(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值