剑指Offer(数据结构与算法面试题精讲)C++版——day3

剑指Offer(数据结构与算法面试题精讲)C++版——day3

      • 题目一:数组中和为0的3个数字
      • 题目二:和大于或等于k的最短子数组
      • 题目三:乘积小于k的子数组

题目一:数组中和为0的3个数字

在这里插入图片描述
    前面我们提到,在一个排序之后的数组中快速找到何为0的两个数,采用左右双指针向中间收拢的方式,一次遍历即可完成。因此,对于这里的3个数和为0,可以先对整个数组排序,然后取出其中一个数,这样问题就变成了在剩下数中查找两个数,使得两个数的和为0。这种方式对应的时间复杂度为,对数组排序的时间,和对元素遍历查找3个数和为0的时间复杂度,如果使用快速排序,时间即为O(nlogn)和O(n^2), 综合下来的时间复杂度为O(n^2)。

# include <iostream>
# include <algorithm>
using namespace std;
void printTriple(int arr[],int len) {int before=0,sum=0;for(int i=0; i<len; ++i) {if(i!=0&&arr[i]==before) {//防止重复遍历第一个数 continue;}for(int p=i+1,q=len-1; p<len&&p<q;) {//选完第一个数之后只遍历之后的数 while(p+1<len&&arr[p+1]==arr[p])p++;//过滤重复 while(q-1>=0&&arr[q-1]==arr[q])q--;sum=arr[i]+arr[p]+arr[q];if(!sum) {//拿到结果之后接着找其他可能组合 cout<<"["<<arr[i]<<","<<arr[p]<<","<<arr[q]<<"]"<<endl;p++;q--;} else if(sum>0) {//移动指针 q--;} else {p++;}}before=arr[i];}}
int main() {int arr[]= {-1,0,1,2,-1,-4,-1,2};int len=sizeof(arr)/sizeof(arr[0]);sort(arr,arr+len);for(int i=0; i<len; ++i) {cout<<arr[i]<<" ";}cout<<endl;printTriple(arr,len);return 0;
}

    注意,还有一点,题目中要求不能够重复,这里需要对每次取出的第一个进行标记before,记录是否访问过。这样能够保证三个数中第一个选择的数据不会重复,另外,为了保证后续选择的两个数不会重复,这里只取顺序排列之后的数(即排序之后右边的数)来检测,比如这里数组为[-1,0,1,2,-1,-4],排序之后得到[-4,-1,-1,0,1,2],由于before的过滤,第一个被选择的数依次为[-4,-1,0,1,2],我们以第一个数为-1举例,对于查找剩下的两个数,我们从-1之后,即[-1,0,1,2]中使用左右指针向中间逼进的方式遍历,可以找到三元组[-1,-1,2],找到之后两个指针同时向中间逼进,最终可以找到余下的[-1,0,1]。再来分析为什么这样找不会漏掉,因为如果选中一个数之后,它可以和它左边的数构成目标三元组,那么在遍历左边的数的时候就会已经找到了。

题目二:和大于或等于k的最短子数组

在这里插入图片描述
    这道题采用经典的双指针法来解决十分合适。我们设置两个指针,不妨分别设为 pq 。这两个指针在数组上滑动,它们之间所涵盖的数构成了用于求和的子数组。算法开始时,我们先让指针 pq 都指向数组的起始位置。然后进入迭代过程:当 pq 之间子数组的和小于目标值 k 时,意味着当前子数组的元素总和还不够大,我们就将右侧的指针 q 向右移动一位,把 q 所指向的新元素纳入子数组,以此增大子数组的和。而当 pq 之间子数组的和大于或等于 k 时,说明子数组可能包含了过多的元素,此时将指针 p 向右移动一位,把 p 原来指向的元素从子数组中剔除,来尝试缩短子数组的长度,进而减小子数组的和。不断重复上述操作,在这个过程中持续调整子数组的范围和元素组成,直到满足特定的条件或者遍历完整个数组。基于这样的思路,我们就可以得到如下代码来实现这一算法。

# include <iostream>
# include <algorithm>
using namespace std;
int findMinLength(int arr[],int len,int k) {int p=0,q=0,min=INT_MAX,sum=arr[0];while(p<=q) {if(sum<k) {//和不够,尝试右移右指针 if(q+1<len) {sum+=arr[++q];} else {//如果不能右移,结束检测 break;}} else {//够了,尝试缩小长度 if(min>q-p+1) {min=q-p+1;}sum-=arr[p++];}}return min;
}
int main() {int arr[]= {5,1,4,3};int len=sizeof(arr)/sizeof(arr[0]);int k=7;cout<<"输出最小长度:"<<findMinLength(arr,len,k);return 0;
}

    这样,只需要在时间复杂度为O(n)的情况下就能够找到最小长度了。我们对这种方法进行提炼,通过移动双指针,能够帮助我们在时间复杂度为O(n)下遍历到所有可能的子数组。你可能说这不是两个数组下标吗,为什么要称为双指针呢,其实这是和链表那块做统一,之前在前端面试的时候,面试官问我字符串逆序怎么处理,我当时也是第一次听说双指针这个概念,我当时还在想JavaScript也没指针这个概念,后来才接受了这个概念,当提到算法的时候我们这么表达可能面试官也能更快的理解你所说的方法或思想。

题目三:乘积小于k的子数组

在这里插入图片描述
    这道题和前面的方法很相似,整体上还是利用双指针来进行遍历。思路为,通过左指针p和右指针q来遍历,对于两个指针中间的子数组,分为两种情况,如果子数组乘积小于k,那么说明此时保持右指针不变,左指针向右移动得到的所有子数组都满足要求,通过这种方式边能够最大化查找子数组,在得到左指针超过右指针后,恢复指向,同时向原数组中新增一个元素,再次遍历,如果没有新元素可以加入,那么说明所有的子数组都被遍历完成,算法终止。
    对于时间复杂度,最坏情况下,数组中的所有子数组都是成立的。由于右指针q需要遍历所有的元素,那么也就是子数组长度为1,2,3,…,n,其中每一个子数组中,都可以固定右指针q,不断移动左指针p,那么对应的时间复杂度为O(n^2)。

# include <iostream>
# include <algorithm>
using namespace std;
int findChildArr(int arr[],int len,int k) {int p=0,q=0,product=arr[0],count=0;while(p<=q) {if(product<k) {//当前子数组满足条件,则保持右指针不变,移动左指针可以拿到所有子数组 int tmp=p;while(p<=q) {count++;++p;}p=tmp;//恢复指针指向,同时在子数组中加入新元素 if(q<len-1) {product*=arr[++q];} else {break;}} else {product/=arr[p++];}}return count;
}
int main() {int arr[]= {10,5,2,6};int len=sizeof(arr)/sizeof(arr[0]);int k=100;cout<<"这样的数组个数为:"<<findChildArr(arr,len,k);return 0;
}

在这里插入图片描述

    最后,在编写双指针算法时,我发现了一个问题,如果使用++q或者q++这样的表达,一定要细致。比如第一次编写算法三的时候,将product/=arr[p++];写成了product/=arr[++p];查了半天才发现问题。

    我是【Jerry说前后端】,本系列精心挑选的算法题目全部基于经典的《剑指 Offer(数据结构与算法面试题精讲)》。在如今竞争激烈的技术求职环境下,算法能力已成为前端开发岗位笔试考核的关键要点。通过深入钻研这一系列算法题,大家能够系统地积累算法知识和解题经验。每一道题目的分析与解答过程,都像是一把钥匙,为大家打开一扇通往高效编程思维的大门,帮助大家逐步提升自己在数据结构运用、算法设计与优化等方面的能力。
    无论是即将踏入职场的应届毕业生,还是想要进一步提升自己技术水平的在职开发者,掌握扎实的算法知识都是提升竞争力的有力武器。希望大家能跟随我的步伐,在这个系列中不断学习、不断进步,为即将到来的前端笔试做好充分准备,顺利拿下心仪的工作机会!快来订阅吧,让我们一起开启这段算法学习之旅!

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

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

相关文章

全新UI好看404页面源码

源码介绍 全新UI好看404页面源码,源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行 效果预览 源码获取 全新UI好看404页面源码

递归典例---汉诺塔

https://ybt.ssoier.cn/problem_show.php?pid1205 #include<bits/stdc.h> #define endl \n #define pii pair<int,int>using namespace std; using ll long long;void move(int n,char a,char b,char c) // n 个盘子&#xff0c;通过 b&#xff0c;从 a 移动到 …

php的高速缓存

部署方法 在我们安装的nginx中默认不支持memc和srcache功能&#xff0c;需要借助第三方模块来让nginx支持此功能。 tar zxf srcache-nginx-module-0.33.tar.gz tar zxf memc-nginx-module-0.20.tar.gz 下载这俩个模块&#xff0c;然后编译安装的时候加进去 编译安装完成之后…

视频设备轨迹回放平台EasyCVR打造视频智能融合新平台,驱动智慧机场迈向数字新时代

一、行业背景​ 随着 5G、AI、物联网、大数据等前沿技术的不断更新换代&#xff0c;交通行业进入数字化转型的高速发展时期。航空业作为交通领域的重要部分&#xff0c;数字化进程从追求速度往注重质量的转变。但机场在数字化转型中面临许多严峻挑战&#xff0c;如现有运营模式…

【论文阅读】Anchor Graph Network for Incomplete Multiview Clustering

摘要 近年来&#xff0c;不完全多视图聚类&#xff08;IMVC&#xff09;受到广泛关注。然而&#xff0c;现有研究仍然存在以下几个不足之处&#xff1a;1) 部分方法忽略了样本对在全局结构分布中的关联性&#xff1b;2) 许多方法计算成本较高&#xff0c;因此无法应用于大规模…

15. 远程服务器运行jemter的GUI方式

1. 问题 在 linux 服务器或远程服务器上&#xff0c;安装 Jmeter&#xff0c;打不开 Jmeter 的 GUI 界面。 环境&#xff1a; linux 服务器mac 电脑 需求&#xff1a;在远程服务器中&#xff0c;启动 jmeter&#xff08;./bin/jmeter &&#xff09;后&#xff0c;在 ma…

Ansible:playbook的高级用法

文章目录 1. handlers与notify2. tags组件3. playbook中使用变量3.1使用 setup 模块中变量3.2在playbook 命令行中定义变量3.3在playbook文件中定义变量3.4使用变量文件3.5主机清单文件中定义变量主机变量组&#xff08;公共&#xff09;变量 1. handlers与notify Handlers&am…

什么是msvcp140.dll?msvcp140.dll丢失的解决方法又有哪些?

msvcp140.dll 是 Microsoft Visual C Redistributable 的核心动态链接库文件&#xff0c;许多软件和游戏依赖它来运行。当系统提示“msvcp140.dll丢失”时&#xff0c;意味着该文件无法被正确加载&#xff0c;导致程序崩溃或无法启动。本文将提供最全面的 msvcp140.dll丢失的解…

(九)图形管线

一图说明问题 顶点数据->顶点着色器->细分着色器->几何着色器->光栅化->片元着色器->颜色混合 创建图形管线函数放在后面位置 void MyApplication::initVulkan() { createInstance(); createSurface(); pickPhysicalDevice(); createLogicalDevice(); cre…

《inZOI(云族裔)》50+MOD整合包

载具 RebelCore - 年龄和时间 mod启动器 优化补丁 去除雾气 坦克模型 菜单 前置 跳过启动 更好性能 等 共计50MOD整合 在游戏的世界里&#xff0c;追求更丰富、更优质的体验是玩家们永恒的主题。RebelCore 这款游戏通过精心打造的 50MOD 整合&#xff0c;为玩家带来了前所未有的…

国家天文台携手阿里云,发布国际首个太阳大模型“金乌”

2025年4月1日&#xff0c;中国科学院国家天文台与阿里云共同宣布推出全球首个太阳物理大模型“金乌”&#xff0c;在太阳活动预测领域实现颠覆性突破——其针对破坏性最强的M5级太阳耀斑预报准确率高达91%&#xff0c;远超传统数值模型&#xff0c;标志着人类对太阳的认知迈入“…

U盘实现——BOT 常用命令

文章目录 U盘实现——BOT 常用命令命令格式CBWCSW数据传输条件命令传输数据传输状态传输命令汇总INQUIRY Command:12h数据格式抓包READ FORMAT CAPACITIES Command: 23h数据格式抓包READ CAPACITY Command: 25h数据格式抓包TEST UNIT READY Command: 00h数据格式抓包WRITE(10) …

【Axure元件分享】月份范围选择器

Axure月份范围选择器是一个月份范围下拉筛选元件&#xff0c;支持月份范围定义选择。组件自动加载系统当前年月份作为默认值&#xff0c;用户可通过箭头图标或键盘快捷键快速切换年份月份&#xff0c;其样式支持高度定制&#xff0c;包括颜色主题、字体尺寸及交互反馈&#xff…

JavaScript基础-移动端常用开发框架

随着移动互联网的发展&#xff0c;越来越多的应用和服务需要支持移动设备。为了提高开发效率和用户体验&#xff0c;开发者们依赖于一些成熟的JavaScript框架来构建响应迅速、功能丰富的移动Web应用。本文将介绍几款广泛使用的移动端开发框架&#xff0c;并通过具体的示例展示它…

数字人训练数据修正和查看 不需要GPU也能运行的DH_live-加载自己训练-

自己训练模pth报错 le "D:\ai\dh_live\app.py", line 42, in demo_mini interface_mini(asset_path, wav_path, output_video_name) File "D:\ai\dh_live\demo_mini.py", line 21, in interface_mini renderModel_mini.loadModel("checkpoi…

基姆拉尔森计算公式

基姆拉尔森计算公式&#xff08;Zellers Congruence 的变体&#xff09;是一种快速根据公历日期计算星期几的数学公式。其核心思想是通过对年月日的数值进行特定变换和取模运算&#xff0c;直接得到星期几的结果。 公式定义 对于日期 年-月-日&#xff0c;公式如下&#xff1a…

数字孪生在智慧城市中的前端呈现与 UI 设计思路

一、数字孪生技术在智慧城市中的应用与前端呈现 数字孪生技术通过创建城市的虚拟副本&#xff0c;实现了对城市运行状态的实时监控、分析与预测。在智慧城市中&#xff0c;数字孪生技术的应用包括交通流量监测、环境质量分析、基础设施管理等。其前端呈现主要依赖于Web3D技术、…

基于CNN-LSTM的深度Q网络(Deep Q-Network,DQN)求解移动机器人路径规划,MATLAB代码

一、深度Q网络&#xff08;Deep Q-Network&#xff0c;DQN&#xff09;介绍 1、背景与动机 深度Q网络&#xff08;DQN&#xff09;是深度强化学习领域的里程碑算法&#xff0c;由DeepMind于2013年提出。它首次在 Atari 2600 游戏上实现了超越人类的表现&#xff0c;解决了传统…

结构型设计模式。持续更新

结构型 - 外观 提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口&#xff0c;从而让子系统更容易使用。 public class SubSystem {public void turnOnTV() {System.out.println("turnOnTV()");}public void setCD(String cd) {System.out.println(&quo…

从零构建大语言模型全栈开发指南:第五部分:行业应用与前沿探索-5.1.2行业落地挑战:算力成本与数据隐私解决方案

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 从零构建大语言模型全栈开发指南-第五部分:行业应用与前沿探索5.1.2 行业落地挑战:算力成本与数据隐私解决方案1. 算力成本挑战与优化策略1.1 算力成本的核心问题1.2 算力优化技术方案2. 数据隐私挑战…