第423场周赛:检测相邻递增子数组 Ⅰ、检测相邻递增子数组 Ⅱ、好子序列的元素之和、统计小于 N 的 K 可约简整数

Q1、检测相邻递增子数组 Ⅰ

1、题目描述

给你一个由 n 个整数组成的数组 nums 和一个整数 k,请你确定是否存在 两个 相邻 且长度为 k严格递增 子数组。具体来说,需要检查是否存在从下标 ab (a < b) 开始的 两个 子数组,并满足下述全部条件:

  • 这两个子数组 nums[a..a + k - 1]nums[b..b + k - 1] 都是 严格递增 的。
  • 这两个子数组必须是 相邻的,即 b = a + k

如果可以找到这样的 两个 子数组,请返回 true;否则返回 false

子数组 是数组中的一个连续 非空 的元素序列。

2、解题思路

要解决这个问题,我们需要检查数组 nums 中是否存在两个相邻的严格递增子数组,且每个子数组的长度为 k。因此,可以将问题分解为以下步骤:

  1. 检查递增子数组:我们先遍历 nums,找出从每个索引 i 开始的长度为 k 的子数组是否为严格递增。
  2. 相邻递增子数组检查:如果在遍历过程中找到了满足条件的相邻严格递增子数组,则返回 true。如果遍历结束没有找到,返回 false。

3、解题过程

  1. 从数组的每个索引 i 开始,检查 nums[i..i+k-1] 是否严格递增。
  2. 如果 nums[i..i+k-1]nums[i+k..i+2*k-1] 都是严格递增的,且满足两个子数组是相邻的,则返回 true
  3. 如果遍历完毕没有找到满足条件的子数组,则返回 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严格递增

子数组。具体来说,需要检查是否存在从下标 ab (a < b) 开始的 两个 子数组,并满足下述全部条件:

  • 这两个子数组 nums[a..a + k - 1]nums[b..b + k - 1] 都是 严格递增 的。
  • 这两个子数组必须是 相邻的,即 b = a + k

返回 k最大可能 值。

子数组 是数组中的一个连续 非空 的元素序列。

2、解题思路

在给定问题中,我们的目标是寻找两个相邻且严格递增的子数组,并且最大化长度 𝑘。当前的超时可能由于在每个候选长度 k 上都逐一检查数组所致。为此,我们可以对每个元素的递增情况进行一次遍历,预处理连续的递增段信息,然后利用这些信息来快速验证长度为 k 的相邻递增子数组是否存在。

  1. 递增段预处理:

    • 预先处理 nums 中每个位置 i 的最长递增序列长度 increasing_lengths[i],表示从位置 i 开始的最长递增序列的长度。

    • 通过一次遍历即可获取此信息。

  2. 二分查找确定最大 𝑘 :

    • 使用二分查找寻找最大的 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. 转移公式
  1. 遍历数组中的每个元素 x:

    • 对于每个 x,好子序列可以从以下几种情况构成:

      1. 独立的好子序列:长度为 1,计数为 1,元素和为 x。
      2. 连接到 x-1 的好子序列:可以接在所有以 x-1 结尾的好子序列后。
      3. 连接到 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[x1]+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[x1]+f[x+1]+x×cnt[x]

  2. 遍历完成后,所有好子序列的总和为 sum ( f [ x ] ) \text{sum}(f[x]) sum(f[x])

4. 使用哈希表

由于元素可能不是连续的,我们使用哈希表 fcnt 记录每个元素对应的状态,避免无意义的内存浪费。

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、解题思路

  1. 二进制分位处理

    • 每个小于 s 的数字可以看作是一个二进制字符串,类似数位 DP 的思想,我们逐位构造合法的数字。

    • 在构造过程中记录数字的置位数量,并确保这些数字小于 s

  2. 预计算 k-可约简性

    • 对于每个可能的置位数 ones_count,我们计算数字是否能在 k 次操作内归约到 1。

    • 使用函数 reduction_steps[x] 表示数字 x 需要的操作次数:

      • reduction_steps[x] = reduction_steps[popcount(x)] + 1,其中 popcount(x) 表示 x 的置位数。
  3. 动态规划

    • 定义 dfs(pos, remaining_ones, is_limit)

      • pos 表示当前处理的位。
      • remaining_ones 表示需要匹配的置位数量。
      • is_limit 表示当前是否受限于数字 s
    • 每次枚举当前位是否为 1,并递归处理剩余的位。

  4. 合并结果

    • 遍历所有可能的 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) 空间。


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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue 与 vue-json-viewer 实现 JSON 数据可视化

前言 接口的调试和测试是确保系统稳定性的重要步骤。为了让开发人员和测试人员能够直观地查看接口返回的 JSON 数据&#xff0c;使用合适的工具至关重要。vue-json-viewer 插件为 vue 开发者提供了一个简单而强大的解决方案。本文将详细介绍如何在 vue 项目中使用该插件&#x…

开源项目stable-diffusion-webui部署及生成照片

参考链接 https://www.freedidi.com/13133.html 基础环境部署 python 官网链接 Python Release Python 3.10.6 | Python.org 下载 Python 3.10.6 版本安装包 下载好后双击 点击安装&#xff0c;这里需要选择一下&#xff0c;把环境变量加上。&#xff08;这里是默认安装到C盘…

宝塔面板 申请证书后 仍然提示不安全

证书显示有效&#xff0c;但是网站显示不安全 导致的原因是引入静态文件使用的是HTTP&#xff0c;查看方法为F12打开console控制台 可以看到静态文件全部都是HTTP 网站采用wordpress搭建&#xff0c;基于问题解决&#xff0c;其他方式搭建也是一样&#xff0c;处理掉所有的H…

14X505-1《火灾自动报警系统设计规范图示》中相关数据和总线制的个人理解

目录 内容简介一、设计容量1.1 设备总数or地址总数1.2 报警与联动合用总线怎么办1.3 10%余量 二、总线短路隔离器2.1 设备总数or地址总数2.2 短路隔离器计入设备数吗2.3 电源要隔离吗2.4 穿越没有设备的防火分区要加短路隔离吗2.5 思考&#xff1a;一个回路可以带几个短路隔离器…

PCB印刷电路板快速上手04电容元件

1.电容元件 电容&#xff1a;又叫电容器&#xff0c;是指容纳电荷本领的物理量。 电容元件是表征电路元件储存电荷特性的理想元件&#xff0c;在电路分析学科中是除电阻元件、电感元件以外的基本电路元件。 电容一般用通常用“C”表示&#xff08;Capacitance&#xff09; 电…

风水算命系统架构与功能分析

系统架构 服务端&#xff1a;Java&#xff08;最低JDK1.8&#xff0c;支持JDK11以及JDK17&#xff09;数据库&#xff1a;MySQL数据库&#xff08;标配5.7版本&#xff0c;支持MySQL8&#xff09;ORM框架&#xff1a;Mybatis&#xff08;集成通用tk-mapper&#xff0c;支持myb…

HarmonyOS NEXT开发进阶(六):HarmonyOS NEXT实现嵌套 H5 及双向通信

文章目录 一、前言二、鸿蒙应用加载Web页面2.1 加载网络地址页面2.2 加载本地H5页面 三、实现Web组件 H5 层与鸿蒙应用层进行相互通讯3.1 鸿蒙应用向 H5 页面发送数据3.2 H5页面向鸿蒙应用发送数据 四、拓展阅读 一、前言 随着HarmonyOS NEXT的快速发展&#xff0c;越来越多的…

OPT: Open Pre-trained Transformer语言模型

摘要 大规模语言模型通常需要数十万计算日的训练时间&#xff0c;展现了在零样本和小样本学习中的显著能力。鉴于其计算成本之高&#xff0c;这些模型在没有大量资本投入的情况下难以复现。对于那些通过API提供的少数模型&#xff0c;研究者无法获取完整的模型权重&#xff0c…

探索图像编辑的无限可能——Adobe Photoshop全解析

文章目录 前言一、PS的历史二、PS的应用场景三、PS的功能及工具用法四、图层的概念五、调整与滤镜六、创建蒙版七、绘制形状与路径八、实战练习结语 前言 在当今数字化的世界里&#xff0c;视觉内容无处不在&#xff0c;而创建和编辑这些内容的能力已经成为许多行业的核心技能…

ffmpeg 编译遇到的坑

makeinfo: error parsing ./doc/t2h.pm: Undefined subroutine &Texinfo::Config::set_from_init_file called at ./doc/t2h.pm line 24. 编译选项添加&#xff1a; --disable-htmlpages

CSS | 实现三列布局(两边边定宽 中间自适应,自适应成比)

目录 示例1 &#xff08;中间自适应 示例2&#xff08;中间自适应 示例3&#xff08;中间自适应 示例4 &#xff08;自适应成比 示例5&#xff08;左中定宽&#xff0c;右边自适应 示例6&#xff08;中间自适应 示例7&#xff08;中间自适应 示例8&#xff08;中间定宽…

《自动驾驶与机器人中的SLAM技术》ch9:自动驾驶车辆的离线地图构建

目录 1 点云建图的流程 2 前端实现 2.1 前端流程 2.2 前端结果 3 后端位姿图优化与异常值剔除 3.1 两阶段优化流程 3.2 优化结果 ① 第一阶段优化结果 ② 第二阶段优化结果 4 回环检测 4.1 回环检测流程 ① 遍历第一阶段优化轨迹中的关键帧。 ② 并发计算候选回环对…

20250112面试鸭特训营第20天

更多特训营笔记详见个人主页【面试鸭特训营】专栏 250112 1. TCP 和 UDP 有什么区别&#xff1f; 特性TCPUDP连接方式面向连接&#xff08;需要建立连接&#xff09;无连接&#xff08;无需建立连接&#xff09;可靠性可靠的&#xff0c;提供确认、重传机制不可靠&#xff0c…

【Rust】错误处理机制

目录 思维导图 引言 一、错误处理的重要性 1.1 软件中的错误普遍存在 1.2 编译时错误处理要求 二、错误的分类 2.1 可恢复错误&#xff08;Recoverable Errors&#xff09; 2.2 不可恢复错误&#xff08;Unrecoverable Errors&#xff09; 三、Rust 的错误处理机制 3…

v-bind操作class

v-bind操作class 参考文献&#xff1a; Vue的快速上手 Vue指令上 Vue指令下 Vue指令的综合案例 指令的修饰符 文章目录 v-bind操作classv-bind对于样式控制的增强操作class案例(tab导航高亮)操作style操作style案例 结语 博客主页: He guolin-CSDN博客 关注我一起学习&#…

算法妙妙屋-------2..回溯的奇妙律动

回溯算法是一种用于系统性地搜索和解决问题的算法&#xff0c;它以深度优先搜索&#xff08;DFS&#xff09;为基础&#xff0c;用来探索所有可能的解决方案。通过递归地尝试候选解并在必要时回退&#xff08;即“回溯”&#xff09;&#xff0c;它能够高效地解决许多涉及组合、…

【微信小程序】5|我的页面 | 我的咖啡店-综合实训

我的页面 引言 本文将详细解析如何实现一个包含登录注册、多个功能模块跳转以及特定功能展示的“我的”页面。我们将使用 Vant Weapp 组件库来简化开发过程&#xff0c;并确保代码的高级性和条理性。 1. 项目结构 首先&#xff0c;确保你的项目结构如下所示&#xff1a; - …

ssh2详细使用步骤,以及常用方法介绍

开源地址&#xff1a;https://github.com/mscdex/ssh2 ssh2 是一个功能强大的 Node.js 库&#xff0c;用于通过 SSH 协议与远程服务器交互。它支持命令执行、文件上传下载、端口转发等操作&#xff0c;常用于自动化脚本和远程服务器管理。 下面是 ssh2 的详细使用步骤和常用方…

计算机网络速成

前言&#xff1a;最近在做一些动态的crypto&#xff0c;但是配置总搞不好&#xff0c;正好也有学web的想法&#xff0c;就先学学web再回去做密码&#xff0c;速成视频推荐b站建模老哥 目录 计算机网络概述网络的范围分级电路交换网络&#xff08;电路交换&#xff09;报文交换网…

基于springboot+vue的 嗨玩-旅游网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…