【C++】 —— 笔试刷题day_29

article/2025/8/15 20:55:43

一、排序子序列

题目解析

在这里插入图片描述

一个数组的连续子序列,如果这个子序列是非递增或者非递减的;这个连续的子序列就是排序子序列。

现在给定一个数组,然后然我们判断这个子序列可以划分成多少个排序子序列。

例如:1 2 3 2 2 1 可以划分成 1 2 32 2 1两个排序子序列

算法思路

对于这道题,思路就很简单了:

暴力解法

0位置开始遍历,寻找一段连续子序列,直到这一段子序列不满足排序子序列的条件,即找到了一个排序子序列;

然后继续从上次遍历结束位置接着遍历数组,寻找下一个子序列。

贪心优化:

当我们遍历到数组中数值相同的区域时,我们要知道,要找的子序列是非递增或者非递减的;

所以这一段相等的序列,我们可以加到前面或者后面的任意序列中。

所以我们在遇到数值相等的子序列时,继续向后遍历即可。

但是这样我们会发现两个问题:

  1. 如果数组刚开始位置的数据是相等的,我们不知道这段子序列是非递增的还是非递减的;
  2. 我们在遍历过程中会用到下一个位置的值来判断是非递增还是非递减,那最后一个位置该怎么办?

对于数组开头的相等子序列,我们可以直接跳过,因为这一段相等的序列可以加到后面的子序列中;

而对于最后一个位置,如果它不能和前面序列组成一个排序子序列,那就只能让它自己组成一个排序子序列了。

在这里插入图片描述

代码实现

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int arr[N];
int n;
int main() {cin >> n;for (int i = 0; i < n; i++)  cin >> arr[i];int ret = 0;for (int i = 0; i < n; i++) {if (i == n - 1) { //数组最后一个位置ret++;break;}if (arr[i] < arr[i + 1]) {//非递增while (i < n && arr[i] <= arr[i + 1])i++;ret++;} else if (arr[i] > arr[i + 1]) {//非递减while (i < n && arr[i] >= arr[i + 1])i++;ret++;} else {//数组开始位置的相等子序列while (i < n && arr[i] == arr[i + 1])i++;}}cout << ret << endl;return 0;
}

二、消减整数

题目解析

在这里插入图片描述

这道题给定一个正整数H,然后从1开始减,第一次减去1,之后每一次减去的数要么和上一次相等,要么是上一次的两倍;

简单来说就是:h每次减去一个数,x起始是1;之后每一h减去x或者2*xx表示上次减去的数)。

现在,最少需要几次才能将h减到0

算法思路

对于这道题,暴力解法

h每次减去x或者2*x,让它一值减,直到h减到0或者<0

简单来说就是分情况讨论:第一次减去1,之后分别考虑减去x和减去2*x的情况。

这样时间复杂度和空间复杂度都太大了;并且h每一次减也不一定会恰好等于0

贪心优化:

这道题要我们求的是将x减到0的最少次数;

那如果我们的h减去某一个数是无法减到0的,那我们就不用去考虑它了;

所以,我们现在要考虑的是,h减的过程中,减去x能否减到0;减去2*x能否减到0

这个也非常容易判断了,如果hx的整数倍,那减去x就肯定可以减到0;如果h2*x的整数倍,那减去2*x就也能减到0

现在有一个问题,如果h既是x的倍数,也是2*x的倍数, 那是减去x还是2*x呢?

很显然是减去2*X,因为我们要求的是h减到0的最小次数,那可以是减去大的数次数更小啊。

所以我们整体思路就出来了,在减的过程中,判断h2*x的倍数,如果是就减去2*x;如果不是就减去x

在这里插入图片描述

代码实现

#include <iostream>
using namespace std;
int main()
{int t;cin>>t;while(t--){int n;cin>>n;n--;//第一次减去1int ret = 1,x = 1;while(n){if(n % (2*x) == 0)x*=2;n-=x;ret++;}cout<<ret<<endl;}return 0;
}

三、最长上升子序列(二)

题目解析

在这里插入图片描述

对于这道题,给定一个数组,然后我们要找到这个数组中最长严格上升子序列的长度;

严格上升子序列:一个数组删掉其中一些数(可以不删)之后,形成的新数组它是严格上升(非递减)的。

简单来说就是:一个数组的子序列,这个子序列是严格上升的。

现在我们要找到所有上升子序列中长度最长的子序列;然后返回它的长度。

算法思路

对于这道题,一眼看起,可以说毫无思路;这该如何去找啊?

细细看来:

我们要找所有严格上升的子序列,当我们遍历到某一个位置时,我们要知道这个位置的数据和前面位置的数据是否能够形成严格上升的子序列;所以我们就要知道这个位置前面有多少个严格上升的子序列,这个位置的数据能放到哪些子序列当中去?

所以我们就要记录:当前所有的严格上升子序列,以及子序列中的元素。

那我们如何去记录所有的严格上升子序列呢?

当遍历到一个位置时:

这个位置如果是大于等于前面所有位置的,那我们可以把这个位置的元素放到任意一个子序列的后面形成一个新的子序列;

但是,我们没有必要去把这个元素放到每一个子序列的后面形成新的子序列。

加入前面有子序列11,21,2,4,当前位置数据是7,我们可以形成1,71,2,71,2,4,7三个新的子序列;但是我们可以发现长度为2的子序列有两个1,21,7,我们有必要把这两个长度一样的子序列都记录下来吗?

很显然是不需要的,我们只需要记录长度为n的子序列它最后一个元素最小的子序列即可

所以,我们只需要按长度n1,2,3...n)记录子序列即可。

那问题又来了,我们要记录子序列中的所有元素吗?

比如11,21,2,41,2,4,7,我们要记录子序列中的所有元素吗?

当然也是没有必要的;当我们遍历一个位置时,我们只需要判断这个位置的能否和前面的子序列组成新的子序列;我们不需要关心这个子序列是什么,所以我们只需要保存子序列最后一个位置的元素即可。

那现在还有一个问题:遍历一个位置时,它可以与前面子序列形成新的子序列,但是长度不是最大的怎么办?

简答来说:现在有子序列11,21,2,41,2,4,7四个子序列,现在遍历到某一个位置,这个位置的值是3

它可以和1形成1,3但是最后一个元素是3是大于1,2的最后一个元素2的,我们可以不用考虑。

它可以和1,2形成1,2,3,它最后一个元素3是小于1,2,4最后一个元素4的,我们就要修改长度为3的子序列,将4修改成3

OK啊,现在大致明白了这道题如何去解决;

但是我们要遍历一遍数组,而且还要去判断一个某一个位置是否能和前面子序列形成新的子序列,形成新的子序列是否比之前的子序列更好;那就要存放每一个长度的子序列对应的最后一个元素的值;时间复杂度那不就是O(n^2)了,题目明确要求时间复杂度是O(n log N)啊。

二分查找

所以这里我们要使用二分算法去优化查找。

当我们遍历到一个位置时,当这个位置的值是>=dp[pos](大于长度最大的子序列的最后一个位置),它可以和长度最大的子序列形成一个新的子序列,长度就是pos+1,直接新增一个位置即可(dp[pos+1] = x)。

但是如果这个位置的值是小于长度最大的子序列的最后一个位置,它可能可以和前面的某一个子序列形成新的子序列,而形成新的子序列的最后一个位置的值,一定是小于等于之前该长度的子序列最后一个位置的值的。

所以我们就要找到这个子序列;

我们按暴力查找它的时间复杂度是O(n);但是我们仔细思考可以发现,我们存放的是长度为n的子序列的最后一个位置的值,那这个数组dp是不是就是非递减的了?

所以我们就可以使用二分查找来搜索这个子序列,而我们要找的也就是>=当前位置的值的区间左端点。

在这里插入图片描述

代码实现

class Solution {public:int dp[100001];int pos = 0;int LIS(vector<int>& a) {for (auto& e : a) {if (pos == 0 || e >= dp[pos])dp[++pos] = e;else {int l = 1, r = pos;while (l < r) {int mid = l + (r - l) / 2;if (dp[mid] >= e)r = mid;elsel = mid + 1;}dp[l] = e;}}return pos;}
};

到这里,本篇文章内容就结束了。
继续加油啊!!!


http://www.hkcw.cn/article/QLagLaZCsc.shtml

相关文章

企业微信自建应用实现接收消息和发送消息功能(python)

# 这一周我不断的琢磨企业微信自建应用并且实现了自建应用的消息接收和发送功能 1.笔记&#xff0c;记录 第一步&#xff1a;打开企业微信后台 https://work.weixin.qq.com 1.1 如果没有企业可以在这里申请&#xff0c;如果有可以直接扫码登录 1.2 打开后台-应用管理-自建应用…

【Rust多线程】Rust并发编程,如何轻松实现无畏并发

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

2025粤港澳信息学创新大赛备考指南Python,C++,图形化历年真题训练题

官方指导文件 训练题目 ZCM5:Python小学组-单项选择题 1.小明安装软件的时候发现软件要求Windows环境&#xff0c;这 个要求限制的是? A.操作系统 B.计算机内存 C.网络设置 D.程序语言 答案‌&#xff1a;A. 操作系统 解析‌&#xff1a;软件运行的环境通常指的是操作系统&am…

【C++指南】“单身狗问题”——只出现一次的数字 系列问题

. &#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 文章目录 引言一、只出现一次的数字&#xff08;一&#xff09;简单题目描述解题思路代码实现及解释 二…

优化 InfluxDB 写入性能:高效批处理策略实战指南

在处理高吞吐量时序数据时&#xff0c;合理运用批处理&#xff08;Batching&#xff09;策略是提升 InfluxDB 写入性能的关键。本文介绍 时间驱动、大小驱动和混合批处理策略&#xff0c;并通过 Python 代码示例展示如何优化数据写入&#xff0c;平衡 延迟与吞吐量。同时&#…

RedwoodJS:乱拳打倒老师傅 NextJS!

RedwoodJS 是一个全栈的 JavaScript/TypeScript 框架&#xff0c;其作用是帮助开发者高效地构建现代化的 Web 应用。它将前端、后端和数据库集成在一起&#xff0c;并使用一种“JAMstack”架构&#xff08;JavaScript、API 和 Markup&#xff09;来构建可扩展的应用程序。 Star…

【C++】 —— 笔试刷题day_18

一、压缩字符串(一) 题目解析 题目给定一个字符str&#xff0c;让我们将这个字符串进行压缩&#xff1b; **压缩规则&#xff1a;**出现多次的字符压缩成字符数字&#xff1b;例如aaa压缩成a3。如果字符值出现一次&#xff0c;1不用写。 算法思路 这道题总的来说就非常简单了…

谷歌浏览器如何禁用javaScript

通过禁用js&#xff0c;可以访问一些设置权限的内容。 Chrome 地址栏输入 chrome://settings/content 回车。 找到 JavaScript 选项。 切换为 不允许网站使用 JavaScript。 地址栏输入&#xff1a; chrome://settings/content/javascript?searchJavaScript Firefox 地址栏输入…

Java从入门到“放弃”(精通)之旅——类和对象全面解析⑦

Java从入门到“放弃”&#xff08;精通&#xff09;之旅&#x1f680;——类和对象全面解析⑦ 一、面向对象初探 1.1 什么是面向对象&#xff1f; Java是一门纯面向对象的语言(OOP)&#xff0c;在面向对象的世界里&#xff0c;一切皆为对象。面向对象是解决问题的一种思想&am…

【Golang】第七弹----map

笔上得来终觉浅,绝知此事要躬行 &#x1f525; 个人主页&#xff1a;星云爱编程 &#x1f525; 所属专栏&#xff1a;Golang &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 1基本介绍 Go语言中的 map …

C/C++程序员为什么要了解汇编?了解汇编有哪些好处?如何学习汇编?

目录 1、概述 2、从汇编的角度去理解问题的若干实例说明 2.1、使用空指针去访问类的数据成员或调用类的虚函数为什么会引发崩溃? 2.2、从汇编代码的角度去理解多线程的执行细节,去理解多线程在访问共享资源时为什么要加锁 2.3、使用Windbg静态分析dump时先从崩溃的那条汇…

基于谐波线性化方法的跟网型GFL并网变流器/VSC宽频序阻抗建模及扫频(Matlab/Simulink平台)及文献复现

目录 1、课程及模型介绍 2、谐波线性化方法介绍 3、跟网型及构网型并网变流器的特点 4、跟网型变流器/VSC拓扑及控制结构 5、不同坐标系下VSC序阻抗建模推导过程 5.1 abc三相坐标系下的VSC序阻抗建模 5.2 d-q旋转坐标系下的VSC序阻抗建模 5.2.1 Park变换及频率偏移效应…

C++“STL之String”

​ 🌹个人主页🌹:喜欢草莓熊的bear 🌹专栏🌹:C++入门 目录 ​编辑 前言 一、STL简介 1.1 STL是什么? 1.2 STL的版本(这个不是很重要了解即可) 1.3 STL的六大组件 二、 String类 2.1为什么要学习String类? 2.1.1 C语言中的字符串…

C++之多态

开始新的征程啦———多态&#xff0c;它也是C的三大特性之一。 文章目录 一、多态的概念二、多态的定义和实现2.1多态的定义2.2 实现动态多态所需要的条件&#xff08;2个&#xff09;2.3 虚函数的定义2.4 虚函数的重写/覆盖2.5 虚函数重写中的问题2.5.1 协变2.5.2 析构函数的…

【第十六届蓝桥杯省赛】比赛心得与经验分享(PythonA 组)

文章目录 一、我的成绩二、我的备赛经历三、如何备赛&#xff08;个人观点&#xff09;1. 基础语法2. 数据结构3. 算法4. 数学 四、做题技巧与注意事项五、我的题解试题A 偏蓝 &#x1f3c6;100%试题B IPV6 &#x1f3c6;0%试题C 2025图形 &#x1f3c6;100%试题D 最大数字 &am…

21天Python计划:零障碍学语法(更新完毕)

文章目录 前言Python 部分MySQL 部分目录结语资料截图 前言 此技术博客专栏围绕 Python 编程和 MySQL 数据库展开了系统且循序渐进的知识讲解&#xff0c;共包含 21 篇文章。 Python 部分 从基础入门逐步深入到高级应用。首先介绍了 Python 的下载和开发工具&#xff0c;为后续…

JavaScript--js基础(详细 全面)

目录 前言: JavaScript 是什么&#xff1f;JavaScript 简介 1.JavaScript历史 2.JavaScript 具有以下特点 第一个JavaScript程序 1.在脚本文件中编写JavaScript代码 2.JavaScript代码执行顺序 基本语法 1.变量 2.数据类型 3.算术运算符 4.赋值运算 5.字符串运算符 6…

Java识别图片或扫描PDF中的文字

目录 使用工具 Java识别图片中的文字 Java识别扫描PDF中的文字 注意事项 图片和扫描文件通常以非文本格式存在&#xff0c;这使得其中的文字信息难以直接编辑、搜索或复制。为了解决这个问题&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术应运而生。OCR通过分析…

【C++】C++11新特性详解:可变参数模板与emplace系列的应用

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriori…

使用宝塔面板快速部署SpringBoot+Vue项目(Java + Node)

使用宝塔面板快速部署SpringBootVue项目&#xff08;Java Node&#xff09; 项目主要技术栈准备工作1. 一台云服务器&#xff08;阿里云、腾讯云等&#xff09;&#xff0c;我这里使用的是阿里云的服务器&#xff08;2核2G&#xff09;2. 已安装宝塔面板3. 已开发完成的Spring…