当前位置: 首页 > article >正文

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

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

      • 题目一:不含重复字符的最长子字符串
      • 题目二:包含所有字符的最短字符串
      • 题目三:有效的回文

题目一:不含重复字符的最长子字符串

在这里插入图片描述

    这里还是可以使用前面,提到的双指针方法,使用左右两个指针定界(不妨记为front和end指针),一开始front指针和end指针都指向第一个字符,显然没有出现重复字符,然后end指针后移,计算这里front指针和end指针之间的子串是否存在重复字符,如果存在重复字符,那么将front前移,重新计算统计是否重复。比如这里的示例,等到front和end指针之间为“bab”时发现重复,于是front前移,front和end之间的子串调整为“ab”,再次检测是否具备重复的字符。由于这里没有强调使用的字符集范围,这里取常用ASCII码作为字符集,这样就能够使用hash表来存储每个字符出现的次数,实现快速存取,于是得到如下代码:

# include <iostream>
# include <algorithm>
using namespace std;
bool isAllOnce(int count[]) {for(int i=0; i<256; ++i) {if(count[i]==2)return false;}return true;
}
int maxSubStrLength(string str) {int i=0,j=0,maxLength=1,len=str.length();int count[256]= {0};for(j=0; j<len; ++j) {count[str[j]]++;if(!isAllOnce(count)) {count[str[i]]--;i++;} else {if(j-i+1>maxLength) {maxLength=j-i+1;}}}return maxLength;
}
int main() {string s1="babcca";cout<<"输出最大不重复子串的长度:"<<maxSubStrLength(s1)<<endl;return 0;
}

在这里插入图片描述
    接下来对上述代码的时间复杂度进行深入分析。在该算法的实现过程中,其中使用的 hash 表被设定大小为 256 。之所以这样设置,是因为它能够较为全面地涵盖可能出现的字符情况。当对这个 hash 表进行扫描操作时,由于其固定大小为 256 ,所以需要进行 256 次判断操作。从算法时间复杂度的概念来讲,尽管存在这 256 次的判断,但由于这个操作次数是一个固定的常量,与输入数据的规模大小并无关联,所以这部分操作的时间复杂度依然属于 O(1) 级别。在此基础上,我们转换视角,站在变量 i ,也就是可以理解为 front 指针的角度来进一步考量。因为在整个算法流程中, front 指针最多只需要从数组的起始位置一直扫描到数组的末尾位置,即最多需要完整地扫描整个数组一次。而数组的长度是由输入数据的规模 n 所决定的,随着 n 的变化, front 指针扫描数组的操作次数也会相应变化,且呈线性关系。综合以上两部分的分析,整体算法最终的时间复杂度也就确定为 O(n) 。

题目二:包含所有字符的最短字符串

在这里插入图片描述
    这里依旧可以考虑使用hash表和双指针的方式来统计是否存在这样的数组。思路大致为,首先扫描一次字符串t,然后标记其中每个字符出现的次数,然后使用双指针遍历s字符串,如果出现了一个子串,使得包含了t中的所有字符,那么统计这个子串和子串的长度,这样便能够遍历完所有子串,每次找到子串之后都更新成最短的那个子串,最终得到如下代码:

# include <iostream>
# include <algorithm>
using namespace std;void initCountNum(string t,int count[]) {for(int i=0; i<256; ++i) {count[i]=0;}for(int i=0,len=t.length(); i<len; ++i) {count[t[i]]++;}
}
bool isEmpty(int count[]) {for(int i=0; i<256; ++i) {if(count[i]>0)return false;}return true;
}
string getMinLenStr(string s,string t) {int count[256]= {0},len1=s.length(),len2=t.length();int i=0,j=len2-1,strLen=-1;string result="";while(j<len1&&i<len1-len2) {initCountNum(t,count);for(int k=i; k<=j; ++k) {count[s[k]]--;}if(isEmpty(count)) {if(j-i+1<strLen||strLen==-1) {strLen=j-i+1;result=s.substr(i,strLen);}i++;} else {j++;}}return result;
}
int main() {string s="ADDBANCAD";string t="ABC";cout<<"输出s中包含t字符的最短子串:"<<getMinLenStr(s,t)<<endl;return 0;
}

在这里插入图片描述
    这里的时间复杂度应该怎么分析呢?对于这里函数涉及比较多的算法,分析时间复杂度可以按照函数进行拆解,这里不妨假设字符串s和字符串t的长度分别为m和n,同上面的分析,对于算法isEmpty都是循环并判断256次,这里的时间复杂度为O(1),对于算法initCountNum时间复杂度为O(m)。接下来,算法的时间复杂度应该着重分析getMinLenStr函数,在双指针遍历时,最坏的情况下,第一次遍历到了最后一个字符才拿到了满足要求的子串,需要遍历n-m次,接下来为了尽可能缩短子串长度,因此左指针右移,这部分还需要的比较次数为n-m次,但由于每次需要初始化计数数组count并且需要扣减计数,因此总时间复杂度为O((m+n)*n)。

题目三:有效的回文

在这里插入图片描述
    回文字符串相关的问题是十分经典且常见的类型,不仅在日常的算法学习和练习中频繁出现,在 LeetCode 上也经常出现。本题的特殊之处在于,题目明确限定了只需要考虑字符串中的字母和数字字符,这一条件为我们的解题思路奠定了基础。基于此,我们的第一步操作便是对原始字符串进行全面且细致的清洗工作。在清洗过程中,需要逐个字符地进行排查,精准地筛选出其中所有的字母和数字字符。同时,对于字母字符里的大写字母,为了保证后续处理的一致性和便捷性,要将其一一转换成对应的小写字母。当完成了字符串的清洗步骤后,就该运用到双指针这一巧妙的算法技巧了。我们设定两个指针,一个处于字符串的最左端,另一个位于字符串的最右端,随后让这两个指针同时朝着字符串的中间方向移动遍历。在遍历的每一个过程中,都要对两个指针所指向的字符内容进行严格比较。一旦发现两个指针指向的内容存在不一致的情况,那么就可以迅速判定这个字符串并非回文串。通过这样严谨且有序的操作流程,我们最终能够实现对回文字符串的准确判断,于是也就得到了如下的代码:

# include <iostream>
# include <algorithm>
using namespace std;bool isPalindrome(string s) {int len=s.length();for(int i=0,j=len-1; i<len/2; ++i,--j) {if(s[i]!=s[j])return false;}return true;
}
string filterStr(string s) {string result="";for(int i=0,len=s.length(); i<len; ++i) {if((s[i]>='a'&&s[i]<='z')||(s[i]>='0'&&s[i]<='9')) {result+=s[i];} else if(s[i]>='A'&&s[i]<='Z') {result+=tolower(static_cast<unsigned char>(s[i]));}}return result;
}
int main() {string s="Was it a cat I saw";cout<<"判断是否是回文字符串:"<<isPalindrome(filterStr(s))<<endl;return 0;
}

在这里插入图片描述
    这里我们需要积累一下,C++下大小写的转换方法,之后字符串系列算法估计还会用到。

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

相关文章:

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

剑指Offer&#xff08;数据结构与算法面试题精讲&#xff09;C版——day6 题目一&#xff1a;不含重复字符的最长子字符串题目二&#xff1a;包含所有字符的最短字符串题目三&#xff1a;有效的回文 题目一&#xff1a;不含重复字符的最长子字符串 这里还是可以使用前面&#x…...

freertos韦东山---事件组以及实验

事件组的原理是什么&#xff0c;有哪些优点&#xff0c;为啥要创造出这个概念 在实时操作系统&#xff08;如 FreeRTOS&#xff09;中&#xff0c;事件组是一种用于任务间同步和通信的机制&#xff0c;它的原理、优点及存在意义如下&#xff1a; 事件组原理 数据结构&#xf…...

架构师面试(二十六):系统拆分

问题 今天我们聊电商系统实际业务场景的问题&#xff0c;考查对业务系统问题的分析能力、解决问题的能力和对系统长期发展的整体规划能力。 一电商平台在早期阶段业务发展迅速&#xff0c;DAU在 10W&#xff1b;整个电商系统按水平分层架构进行设计&#xff0c;包括【入口网关…...

Spring 中的事务

&#x1f9fe; 一、什么是事务&#xff1f; &#x1f9e0; 通俗理解&#xff1a; 事务 一组操作&#xff0c;要么全部成功&#xff0c;要么全部失败&#xff0c;不能只做一半。 比如你转账&#xff1a; A 账户扣钱B 账户加钱 如果 A 扣了钱但 B 没收到&#xff0c;那就出问…...

Java中的同步和异步

一、前言 在Java中&#xff0c;同步&#xff08;Synchronous&#xff09;和异步&#xff08;Asynchronous&#xff09;是两种不同的任务处理模式。核心区别在任务执行的顺序控制和线程阻塞行为。 二、同步&#xff08;Synchronous&#xff09; 定义&#xff1a;任务按顺序执行…...

vue2 vue3 响应式差异

vue2 响应式原理看这 链接: link 总结&#xff1a; object.defineproperty()是对属性的劫持&#xff0c;对属性劫持有两大缺陷 1. 需要遍历对象的所有属性&#xff0c;深层属性需递归&#xff0c;存在效率问题 2. 后添加的属性&#xff0c;无法获得响应式&#xff0c;因为劫持…...

唯一ID生成器设计方案

《亿级流量系统架构设计与实战》总结 1. 唯一ID的核心需求 • 全局唯一性&#xff1a;分布式系统中所有节点生成的ID不可重复。 • 趋势递增性&#xff08;可选&#xff09;&#xff1a;ID按时间或序列递增&#xff0c;优化数据库写入性能。 • 高可用性&#xff1a;服务需72…...

OpenCV 图形API(16)将极坐标(magnitude 和 angle)转换为笛卡尔坐标(x 和 y)函数polarToCart()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 描述 计算二维向量的 x 和 y 坐标。 polarToCart 函数根据 magnitude 和 angle 的对应元素表示的每个二维向量&#xff0c;计算其笛卡尔坐标&#xff1a;…...

在 Ubuntu24.04 LTS 上 Docker Compose 部署基于 Dify 重构二开的开源项目 Dify-Plus

一、安装环境信息说明 硬件资源&#xff08;GB 和 GiB 的主要区别在于它们的换算基数不同&#xff0c;GB 使用十进制&#xff0c;GiB 使用二进制&#xff0c;导致相同数值下 GiB 表示的容量略大于 GB&#xff1b;换算关系&#xff1a;1 GiB ≈ 1.07374 GB &#xff1b;1 GB ≈ …...

安装和配置Docker

其他版本的安装方式可直接参考官方网站&#xff0c;推荐通过官方网站提供的方式安装Dockers&#xff0c;下面只是个演示的示例&#xff0c;仅供参考 Install | Docker Docs 安装 Docker 的前置准备 1.虚拟机配置&#xff1a; 推荐配置 内存&#xff1a;4GB&#xff08;最低…...

Ansible YAML 基础语法与关键词 的详细指南

以下是 Ansible YAML 基础语法与关键词 的详细指南&#xff0c;帮助你快速掌握 Playbook 编写规范和核心概念&#xff1a; 目录 一、Ansible Playbook 基础结构1. YAML 文件基础 二、核心关键词1. Play 定义2. Task 定义3. Handler 定义4. 变量&#xff08;Variables&#xff0…...

NO.64十六届蓝桥杯备战|基础算法-简单贪心|货仓选址|最大子段和|纪念品分组|排座椅|矩阵消除(C++)

贪⼼算法是两极分化很严重的算法。简单的问题会让你觉得理所应当&#xff0c;难⼀点的问题会让你怀疑⼈⽣ 什么是贪⼼算法&#xff1f; 贪⼼算法&#xff0c;或者说是贪⼼策略&#xff1a;企图⽤局部最优找出全局最优。 把解决问题的过程分成若⼲步&#xff1b;解决每⼀步时…...

瑞萨RA4M2使用心得-KEIL5的第一次编译

目录 前言 环境&#xff1a; 开发板&#xff1a;RA-Eco-RA4M2-100PIN-V1.0 IDE&#xff1a;keil5.35 一、软件的下载 编辑瑞萨的芯片&#xff0c;除了keil5 外还需要一个软件&#xff1a;RASC 路径&#xff1a;Releases renesas/fsp (github.com) 向下找到&#xff1a; …...

java根据集合中对象的属性值大小生成排名

1&#xff1a;根据对象属性降序排列 public static <T extends Comparable<? super T>> LinkedHashMap<T, Integer> calculateRanking(List<ProductPerformanceInfoVO> dataList, Function<ProductPerformanceInfoVO, T> keyExtractor) {Linked…...

数据分析-Excel-学习笔记

Day1 复现报表聚合函数&#xff1a;日期联动快速定位区域SUMIF函数SUMIFS函数环比、同比计算IFERROR函数混合引用单元格格式总结汇报 拿到一个Excel表格&#xff0c;首先要看这个表格个构成&#xff08;包含了哪些数据&#xff09;&#xff0c;几行几列&#xff0c;每一列的名称…...

整车CAN网络和CANoe

车载网络中主要包含有Can网络,Lin网络,FlexRay,Most,以太网。 500kbps:500波特率,表示的数据传输的速度。表示的是最大的网速传输速度。也就是每秒 500kb BodyCan车身Can InfoCan娱乐信息Can 车身CAN主要连接的是ESB电动安全带 ADB自适应远光灯等 PTCan动力Can 底盘Can...

ChatGPT 的新图像生成器非常擅长伪造收据

本月&#xff0c;ChatGPT 推出了一种新的图像生成器&#xff0c;作为其 4o 模型的一部分&#xff0c;该模型在生成图像内的文本方面做得更好。 人们已经在利用它来生成假的餐厅收据&#xff0c;这可能会为欺诈者使用的已经很广泛的 AI 深度伪造工具包添加另一种工具。 多产的…...

JS页面尺寸事件

元素位置 在这里插入图片描述 父元素带有定位时输出相对于父亲元素的距离值...

SpringBoot的日志框架

目录 默认日志框架 日志配置 更换日志框架 排除默认Logback 引入目标日志框架 添加配置文件 logback.xml SpringBoot的核心设计宗旨是约定大于配置,很多框架功能都给你默认加载和配置完成供你使用,但这就要求使用者对框架有一定的理解和改造能力,比如这个日志框架,是其…...

网络协议之基础介绍

写在前面 本文看下网络协议相关基础内容。 1&#xff1a;为什么要有网络协议 为了实现世界各地的不同主机的互联互通。 2&#xff1a;协议的三要素 协议存在的目的就是立规矩&#xff0c;无规矩不成方圆嘛&#xff01;但是这个规矩也不是想怎么立就怎么立的&#xff0c;也…...

【学Rust写CAD】34 精确 Alpha 混合函数(argb.rs补充方法)

源码 #[inline]pub fn over_exact(self, dst: Argb) -> Argb {let a 255 - self.alpha32();let t dst.rb() * a 0x80_00_80;let mut rb (t ((t >> 8) & Argb::MASK)) >> 8;rb & Argb::MASK;rb self.rb();// saturaterb | 0x1000100 - ((rb >&…...

利用NumPy核心知识点优化TensorFlow模型训练过程

利用NumPy核心知识点优化TensorFlow模型训练过程 NumPy是Python科学计算的基础库&#xff0c;掌握它的高效操作可以显著提升TensorFlow模型的训练效率。本文详细探讨如何将NumPy的核心优势应用于TensorFlow模型训练的各个环节。 1. 数据预处理优化 高效向量化操作 NumPy的向…...

初识数据结构——Java集合框架解析:List与ArrayList的完美结合

&#x1f4da; Java集合框架解析&#xff1a;List与ArrayList的完美结合 &#x1f31f; 前言&#xff1a;为什么我们需要List和ArrayList&#xff1f; 在日常开发中&#xff0c;我们经常需要处理一组数据。想象一下&#xff0c;如果你要管理一个班级的学生名单&#xff0c;或…...

TDengine 从入门到精通(2万字长文)

目录 第一章:走进 TDengine 的世界 TDengine 是个啥? TDengine 的硬核特性 性能炸裂 分布式架构,天生可扩展 SQL 用起来贼顺手 写入方式花样多 内置缓存,省心又省力 TDengine 能干啥? 智能制造 能源管理 物联网平台 工业大数据 第二章:上手 TDengine:安装与…...

DevOps 与持续集成(CI/CD)

1. DevOps 概述 DevOps(Development + Operations)是一种软件开发方法,强调开发(Dev)与运维(Ops)协作,通过自动化工具提高软件交付效率。其目标是: ✅ 提高部署速度 —— 频繁发布新版本 ✅ 减少人为错误 —— 通过自动化降低运维风险 ✅ 增强可观测性 —— 监控和日…...

[特殊字符] 使用 Handsontable 构建一个支持 Excel 公式计算的动态表格

在 Web 应用中&#xff0c;处理表格数据并提供 Excel 级的功能&#xff08;如公式计算、数据导入导出&#xff09;一直是个挑战。今天&#xff0c;我将带你使用 React Handsontable 搭建一个强大的 Excel 风格表格&#xff0c;支持 公式计算、Excel 文件导入导出&#xff0c;并…...

uniapp微信小程序引入vant组件库

1、首先要有uniapp项目&#xff0c;根据vant官方文档使用yarn或npm安装依赖&#xff1a; 1、 yarn init 或 npm init2、 # 通过 npm 安装npm i vant/weapp -S --production# 通过 yarn 安装yarn add vant/weapp --production# 安装 0.x 版本npm i vant-weapp -S --production …...

贪心进阶学习笔记

反悔贪心 贪心是指直接选择局部最优解&#xff0c;不需要考虑之后的影响。 而反悔贪心是在贪心上面加了一个“反悔”的操作&#xff0c;于是又可以撤销之前的“鲁莽行动”&#xff0c;让整个的选择稍微变得“理智一些”。 于是&#xff0c;我个人理解&#xff0c;反悔贪心是…...

Java 大视界 -- Java 大数据在航天遥测数据分析中的技术突破与应用(177)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

架构师面试(二十七):单链表

问题 今天的问题对于架构师来说会相对容易许多。今天出一个【数据结构与算法】相关的题目&#xff0c;醒醒脑。 给一张【单链表】&#xff0c;该单链表有100个节点元素&#xff08;当然&#xff0c;事先我们是不知道100这个数目的&#xff09;&#xff0c;要获取倒数第8个元素…...