第423场周赛:检测相邻递增子数组 Ⅰ、检测相邻递增子数组 Ⅱ、好子序列的元素之和、统计小于 N 的 K 可约简整数
Q1、检测相邻递增子数组 Ⅰ
1、题目描述
给你一个由 n
个整数组成的数组 nums
和一个整数 k
,请你确定是否存在 两个 相邻 且长度为 k
的 严格递增 子数组。具体来说,需要检查是否存在从下标 a
和 b
(a < b
) 开始的 两个 子数组,并满足下述全部条件:
- 这两个子数组
nums[a..a + k - 1]
和nums[b..b + k - 1]
都是 严格递增 的。 - 这两个子数组必须是 相邻的,即
b = a + k
。
如果可以找到这样的 两个 子数组,请返回 true
;否则返回 false
。
子数组 是数组中的一个连续 非空 的元素序列。
2、解题思路
要解决这个问题,我们需要检查数组 nums 中是否存在两个相邻的严格递增子数组,且每个子数组的长度为 k。因此,可以将问题分解为以下步骤:
- 检查递增子数组:我们先遍历 nums,找出从每个索引 i 开始的长度为 k 的子数组是否为严格递增。
- 相邻递增子数组检查:如果在遍历过程中找到了满足条件的相邻严格递增子数组,则返回 true。如果遍历结束没有找到,返回 false。
3、解题过程
- 从数组的每个索引 i 开始,检查
nums[i..i+k-1]
是否严格递增。 - 如果
nums[i..i+k-1]
和nums[i+k..i+2*k-1]
都是严格递增的,且满足两个子数组是相邻的,则返回true
。 - 如果遍历完毕没有找到满足条件的子数组,则返回
false
。
4、代码实现
class Solution {
public:bool hasIncreasingSubarrays(vector<int>& nums, int k) {int n = nums.size();// 边界情况检查if (n < 2 * k) {return false;}// 遍历数组, 检查相邻的递增子数组for (int i = 0; i <= n - 2 * k; ++i) {bool Increasing = true;// 检查第一个长度为 k 的子数组是否严格递增for (int j = i; j < i + k - 1; ++j) {if (nums[j] >= nums[j + 1]) {Increasing = false;break;}}// 剪枝if (!Increasing) {continue;}// 检查第二个长度为 k 的子数组是否严格递增for (int j = i + k; j < i + 2 * k - 1; ++j) {if (nums[j] >= nums[j + 1]) {Increasing = false;break;}}// 如果相邻的两个子数组都是严格递增的, 则返回 trueif (Increasing) {return true;}}// 遍历完后任未找到符合条件的子数组, 返回 falsereturn false;}
};
Q2、检测相邻递增子数组 Ⅱ
1、题目描述
给你一个由 n
个整数组成的数组 nums
,请你找出 k
的 最大值,使得存在 两个 相邻 且长度为 k
的 严格递增
子数组。具体来说,需要检查是否存在从下标 a
和 b
(a < b
) 开始的 两个 子数组,并满足下述全部条件:
- 这两个子数组
nums[a..a + k - 1]
和nums[b..b + k - 1]
都是 严格递增 的。 - 这两个子数组必须是 相邻的,即
b = a + k
。
返回 k
的 最大可能 值。
子数组 是数组中的一个连续 非空 的元素序列。
2、解题思路
在给定问题中,我们的目标是寻找两个相邻且严格递增的子数组,并且最大化长度 𝑘。当前的超时可能由于在每个候选长度 k 上都逐一检查数组所致。为此,我们可以对每个元素的递增情况进行一次遍历,预处理连续的递增段信息,然后利用这些信息来快速验证长度为 k 的相邻递增子数组是否存在。
-
递增段预处理:
-
预先处理 nums 中每个位置 i 的最长递增序列长度 increasing_lengths[i],表示从位置 i 开始的最长递增序列的长度。
-
通过一次遍历即可获取此信息。
-
-
二分查找确定最大 𝑘 :
- 使用二分查找寻找最大的 k 值。对于每个候选长度 k,快速判断是否存在相邻且严格递增的子数组。
- 在判断过程中,利用 increasing_lengths 数组来验证:如果位置 i 的递增序列长度 increasing_lengths[i] ≥ k 且位置 i + k 的递增序列长度 increasing_lengths[i + k] ≥ k,则位置 i 和 i + k 可以构成所需的相邻递增子数组。
3、代码实现
class Solution {
public:int maxIncreasingSubarrays(vector<int>& nums) {int n = nums.size();// 预处理递增长度vector<int> increasing_lengths(n, 1);for (int i = n - 2; i >= 0; --i) {if (nums[i] < nums[i + 1]) {increasing_lengths[i] = increasing_lengths[i + 1] + 1;}}// 二分查找确定最大 k 值int low = 1, high = n / 2;int maxK = 0;while (low <= high) {int mid = low + (high - low) / 2;bool found = false;// 检查是否存在两个长度为 mid 的相邻递增子数组for (int i = 0; i + 2 * mid - 1 < n; ++i) {if (increasing_lengths[i] >= mid && increasing_lengths[i + mid] >= mid) {found = true;break;}}if (found) {maxK = mid;low = mid + 1;} else {high = mid - 1;}}return maxK;}
};
4、复杂度分析
-
时间复杂度: 预处理 increasing_lengths 数组的复杂度为 O(n)。二分查找过程的复杂度为 O(logn),对于每个候选长度 k,只需 O(n) 的时间验证是否存在符合条件的相邻子数组。因此总复杂度为 O(nlogn)。
-
空间复杂度: O(n),用于存储 increasing_lengths 数组。
Q3、好子序列的元素之和
1、题目描述
给你一个整数数组 nums
。好子序列 的定义是:子序列中任意 两个 连续元素的绝对差 恰好 为 1。
子序列 是指可以通过删除某个数组的部分元素(或不删除)得到的数组,并且不改变剩余元素的顺序。
返回 nums
中所有 可能存在的 好子序列的 元素之和。
因为答案可能非常大,返回结果需要对 109 + 7
取余。
注意,长度为 1 的子序列默认为好子序列。
2、解题思路
1. 子问题拆解
我们要处理的是所有满足条件的子序列,并求它们元素的总和。
这涉及:
- 统计每个元素能够生成多少种好子序列。
- 计算这些子序列的和。
2. 动态规划
设:
cnt[x]
表示以元素 x 结尾的好子序列的个数。f[x]
表示以元素 x 结尾的所有好子序列的元素总和。
3. 转移公式
-
遍历数组中的每个元素 x:
-
对于每个 x,好子序列可以从以下几种情况构成:
- 独立的好子序列:长度为 1,计数为 1,元素和为 x。
- 连接到 x-1 的好子序列:可以接在所有以 x-1 结尾的好子序列后。
- 连接到 x+1 的好子序列:可以接在所有以 x+1 结尾的好子序列后。
-
更新公式:
c n t [ x ] = c n t [ x − 1 ] + c n t [ x + 1 ] + 1 cnt[x] = cnt[x-1] + cnt[x+1] + 1 cnt[x]=cnt[x−1]+cnt[x+1]+1
f [ x ] = f [ x − 1 ] + f [ x + 1 ] + x × c n t [ x ] f[x] = f[x-1] + f[x+1] + x \times cnt[x] f[x]=f[x−1]+f[x+1]+x×cnt[x]
-
-
遍历完成后,所有好子序列的总和为 sum ( f [ x ] ) \text{sum}(f[x]) sum(f[x])。
4. 使用哈希表
由于元素可能不是连续的,我们使用哈希表 f
和 cnt
记录每个元素对应的状态,避免无意义的内存浪费。
3、代码实现
class Solution {
public:int sumOfGoodSubsequences(vector<int>& nums) {// 定义模数const int MOD = 1'000'000'007;// 定义哈希表: f 用于记录元素和, cnt 用于记录以某元素为结尾的子序列个数unordered_map<int, int> f, cnt;// 遍历数组for (int x : nums) {// c 是当前元素 x 能够构成的好子序列个数long long c = (cnt[x - 1] + cnt[x + 1] + 1) % MOD;// 更新以 x 结尾的子序列的总和 f[x]f[x] = (x * c + f[x] + f[x - 1] + f[x + 1]) % MOD;// 更新以 x 结尾的子序列个数 cnt[x]cnt[x] = (cnt[x] + c) % MOD;}// 最终结果为所有元素的 f 值之和long long ret = 0;for (const auto& [_, s] : f) {ret += s;}return ret % MOD; // 返回结果,取模}
};
4、复杂度分析
时间复杂度
- 遍历数组,每个元素更新状态:
- 时间复杂度:O(n),其中 n 是数组长度。
空间复杂度
- 使用哈希表记录 cnt 和 f,存储最多 O(n) 个元素:
- 空间复杂度:O(n)。
Q4、统计小于 N 的 K 可约简整数
1、题目描述
给你一个 二进制 字符串 s
,它表示数字 n
的二进制形式。
同时,另给你一个整数 k
。
如果整数 x
可以通过最多 k 次下述操作约简到 1 ,则将整数 x 称为 k-可约简 整数:
- 将
x
替换为其二进制表示中的置位数(即值为 1 的位)。
例如,数字 6 的二进制表示是 "110"
。一次操作后,它变为 2(因为 "110"
中有两个置位)。再对 2(二进制为 "10"
)进行操作后,它变为 1(因为 "10"
中有一个置位)。
返回小于 n
的正整数中有多少个是 k-可约简 整数。
由于答案可能很大,返回结果需要对 109 + 7
取余。
二进制中的置位是指二进制表示中值为 1
的位。
2、解题思路
-
二进制分位处理:
-
每个小于
s
的数字可以看作是一个二进制字符串,类似数位 DP 的思想,我们逐位构造合法的数字。 -
在构造过程中记录数字的置位数量,并确保这些数字小于
s
。
-
-
预计算 k-可约简性:
-
对于每个可能的置位数
ones_count
,我们计算数字是否能在k
次操作内归约到 1。 -
使用函数
reduction_steps[x]
表示数字x
需要的操作次数:reduction_steps[x] = reduction_steps[popcount(x)] + 1
,其中popcount(x)
表示x
的置位数。
-
-
动态规划:
-
定义
dfs(pos, remaining_ones, is_limit)
:pos
表示当前处理的位。remaining_ones
表示需要匹配的置位数量。is_limit
表示当前是否受限于数字s
。
-
每次枚举当前位是否为
1
,并递归处理剩余的位。
-
-
合并结果:
-
遍历所有可能的
ones_count
,检查reduction_steps[ones_count]
是否小于等于k
。 -
如果满足条件,使用
dfs
统计符合条件的数字个数并累加。
-
3、代码实现
class Solution {
public:int countKReducibleNumbers(string s, int k) {const int MOD = 1'000'000'007;int n = s.length();// 用于记忆化搜索, memo[i][remaining_ones] 表示从第 i 位开始, 剩余 remaining_ones 个置位的合法二进制字符串数目vector<vector<int>> memo(n, vector<int>(n, -1));// 深度优先搜索函数, 返回满足条件的数字个数auto dfs = [&](auto& self, int pos, int remaining_ones, bool is_limit) -> int {// 如果已经处理完所有位, 检查剩余置位是否为 0if (pos == n) {return !is_limit && remaining_ones == 0;}// 如果未受限且已经计算过当前状态, 直接返回记忆化结果if (!is_limit && memo[pos][remaining_ones] != -1) {return memo[pos][remaining_ones];}// 当前位的最大值int upper_bound = is_limit ? s[pos] - '0' : 1;int result = 0;// 枚举当前位可能取的值for (int digit = 0; digit <= min(upper_bound, remaining_ones); digit++) {result = (result + self(self, pos + 1, remaining_ones - digit, is_limit && digit == upper_bound)) % MOD;}// 如果未受限, 则记录当前结果if (!is_limit) {memo[pos][remaining_ones] = result;}return result;};long long total_count = 0;// 预计算每个数字需要多少次操作可以归约到 1vector<int> reduction_steps(n);for (int i = 1; i < n; i++) {reduction_steps[i] = reduction_steps[__builtin_popcount(i)] + 1;}// 遍历所有可能的置位数, 计算合法的数字个数for (int ones_count = 1; ones_count < n; ones_count++) {if (reduction_steps[ones_count] <= k) {// 计算二进制中恰好有 ones_count 个 1 的合法数字个数total_count += dfs(dfs, 0, ones_count, true);total_count %= MOD;}}return total_count;}
};
4、复杂度分析
时间复杂度:
- 预计算
reduction_steps
复杂度为 O ( n 2 ) O(n^2) O(n2)(由于需要对所有可能的数字计算置位数)。 - 每次
dfs
的复杂度为 O ( n 2 ) O(n^2) O(n2),共进行 O ( n ) O(n) O(n) 次,整体为 O ( n 3 ) O(n^3) O(n3)。
空间复杂度:
- 记忆化数组
memo
占用 O ( n 2 ) O(n^2) O(n2) 空间。
相关文章:

第423场周赛:检测相邻递增子数组 Ⅰ、检测相邻递增子数组 Ⅱ、好子序列的元素之和、统计小于 N 的 K 可约简整数
Q1、检测相邻递增子数组 Ⅰ 1、题目描述 给你一个由 n 个整数组成的数组 nums 和一个整数 k,请你确定是否存在 两个 相邻 且长度为 k 的 严格递增 子数组。具体来说,需要检查是否存在从下标 a 和 b (a < b) 开始的 两个 子数组,并满足下…...
hive知识体系
hive知识体系 hive知识体系 链接: 1Hive概览 链接: 2Hive表类型 链接: 3Hive数据抽样 链接: 4Hive计算引擎 链接: 5Hive存储与压缩 链接: 6Hive Sql 大全 链接: 6Hive Sql 大全-Hive 函数 链接: 6Hive Sql 大全-窗口函数 链接: 7Hive执行计划 链接: 8Hive SQL底层执行原理 链接…...

第三篇 Avaya IP Office的架构及其服务组成
所谓的架构,其实就是Solution,解决方案。一般就是如下几套: IPO primary IPO secondaryIPO primary IP500v2IPO primary IPO secondary IP500v2IPO primary IPO secondary IP500v2 Expansion Server(IP500v2,扩展)IPO primaryIPO 500v2 简单的解释…...

AUTOSAR EcuM(ECU状态管理器)
EcuM管理的ECU状态特指ECU的上下电状态。EcuM有两种EcuMFixed和EcuMFlex,其中EcuMFlex是在 AUTOSAR4.x 之后新增的规范文件,相应地原来的 EcuM 改称为 EcuMFixed。EcuMFlex主要是为了适应不同应用场景的各种不同需求,实现更加灵活的处理。所以…...

【PyQt】如何在mainwindow中添加菜单栏
[toc]如何在mainwindow中添加菜单栏 如何在mainwindow中添加菜单栏 主要有两种方法: 1.直接创建mainwindow进行添加 2.使用ui文件加载添加 第二种方法更为常见,可以应用到实际 1.直接创建mainwindow进行添加 import sysfrom PyQt5.QtWidgets import …...

浅谈云计算01 | 云计算服务的特点
在当今数字化时代,云计算作为一种强大的技术解决方案,正逐渐改变着企业和个人对信息技术的使用方式。本文将详细探讨云计算的五个主要特点,包括按需自助服务、广泛的网络接入、资源池化、快速弹性伸缩以及可计量服务。 一、按需自助服务 云…...

【开题报告】基于springboot的煤矿安全监测系统的设计与实现
【开题报告】基于springboot的煤矿安全监测系统的设计与实现 1.选题背景、研究目的及意义 1.1选题背景 煤炭是我国能源行业的重要组成部分,对国民经济具有支撑和推动作用。在煤炭生产过程中存在较高的安全风险,煤矿事故频发,这不仅对人员生…...
微服务中引入消息队列的利弊
微服务中引入消息队列的利弊 1、微服务架构中引入消息队列(Message Queue)的主要优势: 1.1 解耦(Decoupling) 服务之间不需要直接调用,通过消息队列实现松耦合 生产者和消费者可以独立扩展和维护 降低系统间的依赖性 1.2 异步处理(Asynchronous Proc…...
Redis缓存穿透、缓存雪崩和缓存击穿
一、缓存穿透 一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存…...
EF Core分页
Skip(3).Take(8) 最好显式指定排序规则需要知道满足条件的数据的总条数: 用IQueryable的复用 LongCount和Count页数:long pageCount (long)Math.Ceiling(count * 1.0 / pageSize); class Program {static async Task Main(string[] args){using (MyDbC…...

高效设计新选择!用StartAI打造各种风格主题的平铺素材图!
想要打造独特的POD(Print on Demand,按需打印)平铺素材图,却又苦于设计效率低下?别急,今天我来给大家分享一个高效方法,让你轻松秒制各种风格的POD平铺素材图! 具体操作步骤 打开ps…...

大数据技术Kafka详解 ⑤ | Kafka中的CAP机制
目录 1、分布式系统当中的CAP理论 1.1、CAP理论 1.2、Partitiontolerance 1.3、Consistency 1.4、Availability 2、Kafka中的CAP机制 C软件异常排查从入门到精通系列教程(核心精品专栏,订阅量已达600多个,欢迎订阅,持续更新…...

qml Emitter 详解
1、概述 Emitter是QML粒子系统中的一个关键组件,用于创建并发射逻辑粒子。这些逻辑粒子本身不会自动渲染,需要使用一个或多个ParticlePainter元素(如ImageParticle、ItemParticle等)来进行可视化显示。Emitter通过定义粒子的发射…...

【Docker】保姆级 docker 容器部署 MySQL 及 Navicat 远程连接
🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. docker 容器部署 MySQL1.1 拉取mysql镜像1.2 启动容器1.3 进入容器1.4 使用 root 用户登录 2. Navicat 连…...

mybatis-spring @MapperScan走读分析
接上一篇文章:https://blog.csdn.net/qq_26437925/article/details/145100531, 本文注解分析mybatis-spring中的MapperScan注解,则将容易许多。 目录 MapperScan注解定义ConfigurationClassPostProcessor扫描注册beanDefinitionorg.mybatis.s…...

Mysql--架构篇--体系结构(连接层,SQL层,存储引擎层,文件存储层)
MySQL是一种广泛使用的关系型数据库管理系统(RDBMS),其体系结构设计旨在提供高效的数据存储、查询处理和事务管理。MySQL的体系结构可以分为多个层次,每个层次负责不同的功能模块。 MySQL的体系结构主要由以下几个部分组成&#…...

【0x005B】HCI_Write_Default_Erroneous_Data_Reporting命令详解
目录 一、命令概述 二、命令格式及参数 2.1. HCI_Write_Default_Erroneous_Data_Reporting命令格式 2.2. Erroneous_Data_Reporting 三、生成事件及参数 3.1. HCI_Command_Complete事件 3.2. 状态码(Status) 四、命令执行流程 4.1. 命令发起阶段(主机端) 4.2. 命…...
基于 Python 的学生成绩管理系统设计与实现
标题:基于 Python 的学生成绩管理系统设计与实现 内容:1.摘要 摘要:本文介绍了一个基于 Python 的学生成绩管理系统的设计与实现。该系统旨在提高学生成绩管理的效率和准确性,方便教师和学生进行成绩查询和分析。本文详细描述了系统的设计思路、功能模块…...

【Apache Doris】周FAQ集锦:第 29 期
引言 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目! 在这个栏目中,每周将筛选社区反馈的热门问题和话题,重点回答并进行深入探讨。旨在为广大用户和开发者分享有关 Apache Doris 的常见问题。 通过这个每周 FAQ 栏目,希望帮助社…...

【C】初阶数据结构3 -- 单链表
之前在顺序表那一篇文章中,提到顺序表具有的缺点,比如头插,头删时间复杂度为O(n),realloc增容有消耗等。而在链表中,这些问题将得到解决。所以在这一篇文章里,我们将会讲解链表的定义与性质,以及…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...