Leetcode 第 368 场周赛题解

news2024/12/23 20:08:10

Leetcode 第 368 场周赛题解

  • Leetcode 第 368 场周赛题解
    • 题目1:2908. 元素和最小的山形三元组 I
      • 思路
      • 代码
      • 复杂度分析
    • 题目2:2909. 元素和最小的山形三元组 II
      • 思路
      • 代码
      • 复杂度分析
    • 题目3:2910. 合法分组的最少组数
      • 思路
      • 代码
      • 复杂度分析
    • 题目4:2911. 得到 K 个半回文串的最少修改次数
      • 思路
      • 代码
      • 复杂度分析

Leetcode 第 368 场周赛题解

题目1:2908. 元素和最小的山形三元组 I

思路

暴力枚举下标三元组 (i, j, k),更新答案 sum = min(sum, nums[i] + nums[j] + nums[k])。

代码

/*
 * @lc app=leetcode.cn id=2908 lang=cpp
 *
 * [2908] 元素和最小的山形三元组 I
 */

// @lc code=start
class Solution
{
public:
    int minimumSum(vector<int> &nums)
    {
        int n = nums.size();
        int sum = INT_MAX;
        for (int i = 0; i < n - 2; i++)
            for (int j = i + 1; j < n - 1; j++)
                for (int k = j + 1; k < n; k++)
                    if (nums[i] < nums[j] && nums[j] > nums[k])
                        sum = min(sum, nums[i] + nums[j] + nums[k]);
        return sum == INT_MAX ? -1 : sum;
    }
};
// @lc code=end

复杂度分析

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

空间复杂度:O(1)。

题目2:2909. 元素和最小的山形三元组 II

思路

枚举 nums[j] + 前后缀分解。

定义 preMin[i] 为前缀最小值,初始化 preMin[0] = nums[0],递推公式:preMin[i] = min(preMin[i - 1], nums[i])

定义 sufMin[i] 为后缀最小值,初始化 sufMin[n - 1] = nums[n - 1],递推公式:sufMin[i] = min(sufMin[i + 1], nums[i])

枚举 nums[j],答案为 preMin[j - 1] + nums[j] + sufMin[j + 1] 的最小值。

代码

/*
 * @lc app=leetcode.cn id=2909 lang=cpp
 *
 * [2909] 元素和最小的山形三元组 II
 */

// @lc code=start
class Solution
{
public:
    int minimumSum(vector<int> &nums)
    {
        int n = nums.size();
        vector<int> preMin(n);
        preMin[0] = nums[0];
        for (int i = 1; i < n; i++)
            preMin[i] = min(preMin[i - 1], nums[i]);
        vector<int> sufMin(n);
        sufMin[n - 1] = nums[n - 1];
        for (int i = n - 2; i >= 0; i--)
            sufMin[i] = min(sufMin[i + 1], nums[i]);
        int minimumSum = INT_MAX;
        for (int j = 1; j < n - 1; j++)
            if (preMin[j - 1] < nums[j] && nums[j] > sufMin[j + 1])
                minimumSum = min(minimumSum, preMin[j - 1] + nums[j] + sufMin[j + 1]);
        return minimumSum == INT_MAX ? -1 : minimumSum;
    }
};
// @lc code=end

复杂度分析

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

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

题目3:2910. 合法分组的最少组数

思路

贪心。

统计每个数字的出现次数,记在哈希表 hash 中。

假设可以分成大小为 k 和 k+1 的组,现在需要算出对于每个数 num,每个 hash[num] 最少可以分成多少组。

设 q = freq / k,r = freq % k。

如果 q < r 则无法分成 k 和 k+1 组,否则一定可以分组。

在可以分组的前提下,分出的 k+1 越多,组数就越少,所以最少可以分出 ceil(freq / (k + 1)) 组。

累加组数即为分组个数。

从 min⁡(hash[num]) 开始倒着枚举 k,只要可以分,就立刻返回答案。

代码

/*
 * @lc app=leetcode.cn id=2910 lang=cpp
 *
 * [2910] 合法分组的最少组数
 */

// @lc code=start
class Solution
{
public:
    int minGroupsForValidAssignment(vector<int> &nums)
    {
        unordered_map<int, int> hash; // <value, frequency>
        for (const int &num : nums)
            hash[num]++;
        auto cmp = [](const auto &a, const auto &b) -> bool
        {
            return a.second < b.second;
        };
        int k = min_element(hash.begin(), hash.end(), cmp)->second;
        int ans = 0;
        for (;; k--)
        {
            for (auto &[num, freq] : hash)
            {
                int q = freq / k, r = freq % k;
                if (q < r)
                {
                    ans = 0;
                    break;
                }
                ans += ceil((double)freq / (k + 1));
            }
            if (ans)
                break;
        }
        return ans;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n),其中 n 是数组 nums 的长度。设哈希表的大小为 m,哈希表中最小的 value 为 k,由于所有 value 之和为 n,所以 k * m ≤ n 。而循环次数又至多为 k * m,所以时间复杂度为 O(n)。

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

题目4:2911. 得到 K 个半回文串的最少修改次数

思路

题解:预处理+记忆化搜索/递推(附题单!)Python/Java/C++/Go

在这里插入图片描述

代码

/*
 * @lc app=leetcode.cn id=2911 lang=cpp
 *
 * [2911] 得到 K 个半回文串的最少修改次数
 */

// @lc code=start

// 预处理每个数的真因子,时间复杂度 O(MX * log(MX))
const int MX = 201;
vector<vector<int>> divisors(MX);
int init = []
{
    for (int i = 1; i < MX; i++)
        for (int j = i * 2; j < MX; j += i)
            divisors[j].push_back(i);
    return 0;
}();

class Solution
{
public:
    int minimumChanges(string s, int k)
    {
        int n = s.size();
        vector<vector<int>> modify(n - 1, vector<int>(n));
        for (int left = 0; left < n - 1; left++)
            for (int right = left + 1; right < n; right++)
            {
                string subStr = s.substr(left, right - left + 1);
                modify[left][right] = get_modify(subStr);
            }
        vector<vector<int>> memo(k, vector<int>(n, n + 1)); // n+1 表示没有计算过
        function<int(int, int)> dfs = [&](int i, int j) -> int
        {
            if (i == 0)
                return modify[0][j];
            int &res = memo[i][j]; // 注意这里是引用
            if (res <= n)
            { // 之前计算过
                return res;
            }
            for (int L = i * 2; L < j; L++)
                res = min(res, dfs(i - 1, L - 1) + modify[L][j]);
            return res;
        };
        return dfs(k - 1, n - 1);
    }
    // 辅函数 - 计算字符串 s 变成半回文串需要修改的字符数目
    int get_modify(string s)
    {
        int n = s.size(), res = n;
        for (int d : divisors[n])
        {
            int cnt = 0;
            for (int i0 = 0; i0 < d; i0++)
                for (int i = i0, j = n - d + i0; i < j; i += d, j -= d)
                    cnt += s[i] != s[j];
            res = min(res, cnt);
        }
        return res;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n3logn),其中 n 是字符串 s 的长度。时间主要在预处理上,有 O(n2) 个子串,平均每个子串有 O(logn) 个因子,每个因子需要 O(n) 的时间计算修改次数。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1189697.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode124. 二叉树中的最大路径和

Every day a Leetcode 题目来源&#xff1a;124. 二叉树中的最大路径和 解法1&#xff1a;深度优先搜索 思路类似于&#xff1a;Leetcode543. 二叉树的直径&#xff0c;只是考虑对象从边变成了点。 首先&#xff0c;考虑实现一个简化的函数 dfs(node)&#xff0c;该函数计算…

解决 github.com 或者 raw.githubusercontent.com 打开慢、打不开问题

系列文章目录 文章目录 系列文章目录前言一、Windows 系统1.1 以管理员身份运行记事本1.2 打开 hosts 文件1.3 写入 IP 地址 二、Linux2.1 hosts 文件位置 三、Android 系统总结 前言 连接手机热点&#xff0c;将流量关闭马上打开&#xff0c;进入的成功率更高 一、Windows 系…

Linux基础【Linux知识贩卖机】

偶尔的停顿和修整&#xff0c;对于人生是非常必要的。 --随记 文章目录 Linux目录目录结构磁盘分区相关命令 相对路径和绝对路径 文件权限用户分类umask创建文件权限计算方法粘滞位 总结 Linux目录 目录结构 Linux 操作系统采用了一种层次化的目录结构&#xff0c;常被称为标…

11-Docker-Redis集群部署

00-前言 在工作环境中&#xff0c;我们常常被要求配置多种集群&#xff0c;Redis 集群是最常见的入门需要掌握的集群配置方法&#xff0c;在之前的学习中&#xff0c;我们学习掌握了分布式存储的算法&#xff0c;本质上集群的部署就是通过分布式存储算法将数据分发部署好的不同…

2009-2018年全国各省财政透明度数据

2009-2018年全国各省财政透明度数据 1、时间&#xff1a;2009-2018年 2、指标&#xff1a;财政透明度 3、范围&#xff1a;31省 4、来源&#xff1a;财政透明度报告 5、指标解释&#xff1a; 财政透明度是公开透明的重要方面&#xff0c;体现了现代预算制度和法治政府的特…

09-MySQL主从复制

01-主从复制原理 MySQL主从复制是一种用于实现数据备份、读写分离和扩展性的技术。它基于二进制日志&#xff08;Binary Log&#xff09;来将主数据库上的更改操作同步到一个或多个从数据库。 MySQL主从复制的基本原理如下&#xff1a; 主服务器&#xff08;Master&#xff0…

HTTP协议详解-下(Tomcat)

如何构造 HTTP 请求 对于 GET 请求 地址栏直接输入点击收藏夹html 里的 link script img a…form 标签 通过 form 标签构造GET请求 <body><!-- 表单标签, 允许用户和服务器之间交互数据 --><!-- 提交的数据报以键值对的结果来组织 --><form action&quo…

JAVA开源项目 于道前端项目 启动步骤参考

1. 安装 启动过程有9个步骤&#xff1a; 1.1 安装 Node JS , V18版本的 &#xff08;安装步骤省略&#xff09; 1.2 安装 npm install -g yarn &#xff0c;node JS里边好像自带npm &#xff0c;通过npm的命令安装 yarn 1.3 切换到项目中去安装&#xff0c;npm install &a…

5G网络切片,到底是什么?

网络切片&#xff0c;是5G引入的一个全新概念。 一看到切片&#xff0c;首先想到的&#xff0c;必然是把一个完整的东西切成薄片。于是&#xff0c;切面包或者切西瓜这样的画面&#xff0c;映入脑海。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 然而…

如何做游戏软件开发?怎么和软件开发公司合作?

随着科技的发展和普及&#xff0c;游戏软件已经成为人们日常生活和工作中不可或缺的一部分&#xff0c;许多企业也开始涉足游戏软件开发领域&#xff0c;希望能够打造出一款受欢迎的游戏&#xff0c;那么&#xff0c;如何做游戏软件开发?怎么和软件开发公司合作呢?下面我们来…

【Data Grip】打开控制台编写sql语句

这里我从表打开&#xff08;也可以从其他地方打开都行&#xff0c;右键new,出现Query Console 点击即可)控制台&#xff0c;右键表 new 点击query console 在上面编写sql语句 编写完之后 点击绿色三角形运行

某平台简单尝试一次密码逆向

1、查看表单数据 发现密码加密 2、控制台搜索password 发现他在欺负我看不懂拼音 3、第一次断点调试失败 断点后随便填写账号密码登录&#xff0c;发现失败 4、控制台搜索 jiami 又找到了一个函数 5、断点成功 重新登录后断点成功 jiami function(password) {var e passw…

代码随想录训练营Day1:二分查找与移除元素

本专栏内容为&#xff1a;代码随想录训练营学习专栏&#xff0c;用于记录训练营的学习经验分享与总结。 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a;二分查找与移除元素 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a…

Django之三板斧的使用,全局配置文件介绍,request对象方法,pycharm链接数据库,Django链接数据库,ORM的增删改查

【1】三板斧(3个方法)的使用 Httpresponse() 括号内写什么字符串&#xff0c;返回的就是什么字符串返回的是字符串 render(request&#xff0c; 静态文件 ) request是固定的静态文件是写在templates文件夹里面的&#xff0c;如&#xff0c;HTML文件 redirect( 重定向的地址 ) 重…

EfficientNet 系列网络学习

EfficientNet V1 EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks 增加网络参数的方式有三种&#xff1a;深度、宽度和输入图像的分辨率。探究这三种方式对网络性能的影响&#xff0c;以及如何同时缩放这三种因素是 EifficentNet的主要贡献。 单独…

内核移植笔记 Cortex-M移植

常用寄存器 PRIMASK寄存器 为1位宽的中断屏蔽寄存器。在置位时&#xff0c;它会阻止不可屏蔽中断&#xff08;NMI&#xff09;和HardFault异常之外的所有异常&#xff08;包括中断&#xff09;。 实际上&#xff0c;它是将当前异常优先级提升为0&#xff0c;这也是可编程异常/…

【代码随想录】算法训练营 第二十天 第六章 二叉树 Part 6

654. 最大二叉树 题目 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回…

西部数码的域名如何实现DDNS功能

功能简介&#xff1a; 动态域名解析&#xff08;Dynamic DNS&#xff0c;简称DDNS&#xff09;可以让用户使用固定的域名来访问动态IP地址&#xff0c;解决因IP地址变化造成服务无法访问的情况。 本文将介绍如何使用西部数码的API实现DDNS功能&#xff0c;使您的域名始终指向您…

SpringCloudGateway--Sentinel限流、熔断降级

目录 一、概览 二、安装Sentinel 三、微服务整合sentinel 四、限流 1、流控模式 ①直接 ②关联 ③链路 2、流控效果 ①快速失败 ②Warm Up ③排队等待 五、熔断降级 1、慢调用比例 2、异常比例 3、异常数 一、概览 SpringCloudGateway是一个基于SpringBoot2.x的…