代码随想录算法训练营day27

题目:93.复原IP地址、78.子集、90.子集II

参考链接:代码随想录

93.复原IP地址

思路:本题的思路和上题切割回文串类似,也是先要写一个判断函数,然后一个个切割。对返回条件,如果路径长度已经为4,则可以判断是否切割完毕,如果已经切割到最后,则可以把path加入结果;for循环用于判断end即切割位置;递归用于逐个往后切割。时间复杂度O(n*2^n)。

class Solution {
public:bool isValidIp(string s,int begin,int end){//同样我们尽量不用子串,使用begin和end,[begin,end)if(end-begin==1||end-begin>1&&end-begin<=3&&s[begin]!='0'){//长度符合要求,长度为1时可以为任何值,长度为2和3的时候必须满足首位不为0string s1=string(s.begin()+begin,s.begin()+end);//生成子串,使用substr函数也可以int i=stoi(s1);//转换为intif(i>=0&&i<=255){return true;}}return false;}string strToIP(vector<string> &path){//将向量转换为IP地址string ip;ip+=path[0];ip.push_back('.');ip+=path[1];ip.push_back('.');ip+=path[2];ip.push_back('.');ip+=path[3];return ip;}vector<string> ans;vector<string> path;//用于记录路径void backtracking(const string &s,int begin,int end){//end才是第一次切割的位置!if(path.size()==4){//已经达到4的长度if(end>s.size()){//end越界说明已经全部选完了ans.push_back(strToIP(path));}return;}for(int i=end;i<=s.size();i++){if(!isValidIp(s,begin,i)){//第一次切割不满足,直接往后切continue;}path.push_back(string(s.begin()+begin,s.begin()+i));backtracking(s,i,i+1);//如果切到结尾,i+1=size+1path.pop_back();}}vector<string> restoreIpAddresses(string s) {backtracking(s,0,1);return ans;}
};

这里有一个问题,比如25525511135,如果切割了2,5,5,这时判断最后一个不管怎么切割,都要进入下一层递归,实际上这时候已经不可能完成结果,可以进行剪枝处理。可以根据begin和path大小来剪枝,当path长度为1时,如果剩余长度size-begin>9则剪枝,当path长度为2时,剩余长度size-begin>6则剪枝,当path长度为3时,剩余长度size-begin>3则剪枝。可以将其写入for循环的条件判断中。

for(int i=end;i<=s.size()&&s.size()-begin<=3*(4-path.size());i++)

想这个剪枝用了很长时间,在面试的时候如果能通过就不要细想剪枝了。
标答使用的是左闭右闭区间,增加了一个变量portNum,用于记录逗点个数,直接在原来的字符串上增加逗点分割,空间占用比我们更小。标答也没有完全剪枝,只是粗略的根据总长度剪枝了一下。
标答:

class Solution {
private:vector<string> result;// 记录结果// startIndex: 搜索的起始位置,pointNum:添加逗点的数量void backtracking(string& s, int startIndex, int pointNum) {if (pointNum == 3) { // 逗点数量为3时,分隔结束// 判断第四段子字符串是否合法,如果合法就放进result中if (isValid(s, startIndex, s.size() - 1)) {result.push_back(s);}return;}for (int i = startIndex; i < s.size(); i++) {if (isValid(s, startIndex, i)) { // 判断 [startIndex,i] 这个区间的子串是否合法s.insert(s.begin() + i + 1 , '.');  // 在i的后面插入一个逗点pointNum++;backtracking(s, i + 2, pointNum);   // 插入逗点之后下一个子串的起始位置为i+2pointNum--;                         // 回溯s.erase(s.begin() + i + 1);         // 回溯删掉逗点} else break; // 不合法,直接结束本层循环}}// 判断字符串s在左闭又闭区间[start, end]所组成的数字是否合法bool isValid(const string& s, int start, int end) {if (start > end) {return false;}if (s[start] == '0' && start != end) { // 0开头的数字不合法return false;}int num = 0;for (int i = start; i <= end; i++) {if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法return false;}num = num * 10 + (s[i] - '0');if (num > 255) { // 如果大于255了不合法return false;}}return true;}
public:vector<string> restoreIpAddresses(string s) {result.clear();if (s.size() < 4 || s.size() > 12) return result; // 算是剪枝了backtracking(s, 0, 0);return result;}
};

时间复杂度O(3^4),直接根据IP地址的构成计算的时间复杂度。

78.子集

思路:本题要考虑子集的元素个数,在主函数中根据元素个数分类,从0到nums.size()。在回溯函数中,把元素个数k作为一个固定值,当路径长度等于k时返回。其他步骤和前面题目就类似了。剪枝不再过细考虑。时间复杂度O(n^3*2^n),和前面的题目我们多写了一个for循环。

class Solution {
public:vector<vector<int>> ans;vector<int> path;void backtracking(vector<int>& nums,int k,int begin){//k为长度,一直保持不变,begin为开始取的位置if(path.size()==k){//路径长度为k,返回ans.push_back(path);return;}for(int i=begin;i<=nums.size()-1;i++){path.push_back(nums[i]);backtracking(nums,k,i+1);//开始选下一个path.pop_back();}}vector<vector<int>> subsets(vector<int>& nums) {for(int k=0;k<=nums.size();k++){//根据长度分类,0为空集backtracking(nums,k,0);}return ans;}
};

看完标答发现可以不用在主函数中写for循环,可以在每一层取元素的时候就直接将其加入ans中,第一层取1个元素,第二层取2个元素。
标答:

class Solution {
public:vector<vector<int>> ans;vector<int> path;void backtracking(vector<int>& nums,int begin){//k为长度,一直保持不变,begin为开始取的位置if(begin==nums.size()){//开始位置已经到达末尾return;}for(int i=begin;i<=nums.size()-1;i++){path.push_back(nums[i]);ans.push_back(path);//每一层遍历都要直接将结果加入ansbacktracking(nums,i+1);//开始选下一个path.pop_back();}}vector<vector<int>> subsets(vector<int>& nums) {ans.push_back(path);//先加入一个空集backtracking(nums,0);return ans;}
};

时间复杂度O(n*2^n)。

90.子集II

思路:结合之前used去重的思路,加入上题,即为答案。时间复杂度O(n*2^n)。

class Solution {
public:vector<vector<int>> ans;vector<int> path;void backtracking(vector<int>& nums,int begin,vector<int>& used){ans.push_back(path);//先加入自己,这样不用额外添加空集if(begin==nums.size()){return;}for(int i=begin;i<nums.size();i++){if(i>0&&nums[i]==nums[i-1]&&used[i-1]==0){//两个相邻,且前一个未使用过,说明是同一层的,直接跳过continue;}path.push_back(nums[i]);used[i]=1;backtracking(nums,i+1,used);path.pop_back();used[i]=0;}}vector<vector<int>> subsetsWithDup(vector<int>& nums) {sort(nums.begin(),nums.end());vector<int> used(nums.size(),0);//先全部初始化为0backtracking(nums,0,used);return ans;}
};

也可以不用used,不过我们初学者最好用,好理解。

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

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

相关文章

DevEco Studio下载与安装(Windows)

下载地址&#xff1a; HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 安装时直接点击 next 即可。 运⾏已安装的DevEco Studio&#xff0c;⾸次使⽤&#xff0c;请选择Do not import settings&#xff0c;单击OK。 1.安装Node.js 如果本地有下载&#xff0c;可以…

前端JS 时间复杂度和空间复杂度

时间复杂度 BigO 算法的时间复杂度通常用大 O 符号表述&#xff0c;定义为 T(n) O(f(n)) 实际就是计算当一个一个问题量级&#xff08;n&#xff09;增加的时候&#xff0c;时间T增加的一个趋势 T(n)&#xff1a;时间的复杂度&#xff0c;也就相当于所消耗的时长 O&#xff1…

乐吾乐Web可视化RTSP播放

背景 乐吾乐致力于物联网和智能制造等场景的Web可视化平台和解决方案&#xff0c;其中摄像头播放必不可少。 当前国内摄像头都以RTSP协议为主&#xff0c;而HTML不能直接读取RTSP协议&#xff0c;因此需要一个转流服务。乐吾乐Web可视化播放RTSP也是如此&#xff1a; RTSP协…

ArcGIS专用语言:Arcade详细介绍(一)

Arcade语言是专为在ArcGIS中使用而设计的。是一种可移植、轻量级且安全的表达语言&#xff0c;用于在ArcGIS应用程序中创建自定义内容。 与其他表达式语言一样&#xff0c;它可以执行数学计算、设置文本格式和计算逻辑语句&#xff0c;还支持多语句表达式、变量和流控制语句。…

理解计算着色器中glsl语言的内置变量

概要 本文通过示例的方式&#xff0c;着重解释以下几个内置变量&#xff1a; gl_WorkGroupSizegl_NumWorkGroupsgl_LocalInvocationIDgl_WorkGroupIDgl_GlobalInvocationID 基本概念 局部工作组与工作项 一个3x2x1的局部工作组示例如下&#xff0c;每个小篮格子表示一个工作项…

Vulnhub靶机:basic_pentesting_1

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.4&#xff09; 靶机&#xff1a;basic_pentesting_1&#xff08;10.0.2.6&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/en…

密码学——基本概念

引言 在计算机和通信技术发达的现代社会,密码已经成为防止信息被篡改,盗取等方面不可或缺的技术。可应用于:本人身份认证,网上交易加密和认证。保证文件不被篡改的电子签名。电子邮件的加密等等领域。 密码学术语: 密码 cipher 基本词汇: 明文P(Plain text)= 没有经…

TCP缓存

TCP缓存是指TCP协议在数据传输过程中使用的一种机制&#xff0c;用于临时存储和管理数据包。它主要有三个作用&#xff1a;提高网络性能、保证数据的可靠性和实现流量控制。 首先&#xff0c;TCP缓存可以提高网络性能。当发送端发送数据时&#xff0c;TCP协议会将数据分割成若…

如何实现无公网ip远程访问本地安卓Termux部署的MySQL数据库【内网穿透】

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

VR危险环境模拟介绍|VR虚拟现实设备

VR危险环境模拟是指利用虚拟现实技术来模拟和展现各种危险环境&#xff0c;以便训练人员应对紧急情况、提高安全意识和应急反应能力。这种模拟可以涉及到工业、医疗、紧急救援等多个领域&#xff0c;旨在帮助人们在真实环境中面对危险时能够做出正确的应对和决策。 VR危险环境…

Linux alias命令(为复杂命令创建别名,其中命令可带选项或参数)

文章目录 Mastering the Linux alias Command&#xff08;精通Linux的alias命令&#xff09;1. Understanding the alias Command&#xff08;理解alias命令&#xff09;示例Ubuntu20.04 arm操作系统OpenEuler20.03 arm操作系统 2. Basic Usage of alias&#xff08;alias的基本…

AMEYA360:广和通5G智能模组SC171支持Android、Linux和Windows系统,拓宽智能物联网应用

世界移动通信大会2024期间&#xff0c;广和通宣布&#xff1a;5G智能模组SC171除支持Android操作系统外&#xff0c;还兼容Linux和Windows系统&#xff0c;帮助更多智能终端客户快速迭代产品&#xff0c;拓宽智能化应用覆盖范围。 广和通SC171系列基于高通QCM6490物联网解决方案…

基于Python3的数据结构与算法 - 07 归并排序

一、归并 引入 假设现在的列表分两段有序&#xff0c;如何将其合并成为一个有序列表。 这种操作成为一次归并。 归并的思路 分别对两个列表进行遍历&#xff0c;比较两个列表中的最小值&#xff0c;将更小的取出来。取出后一次进行上操作&#xff0c;直到其中一个列表中的元…

springboot+vue实现Minio文件存储

安装minio 首先点击进入MINIO官网&#xff0c;进行一个minio服务器的下载 下载好了之后在本地磁盘找一个文件夹&#xff0c;把下载的exe放入文件夹&#xff0c;再新建一个文件夹准备存放数据和文件 在当前目录cmd进入控制台&#xff0c;输入代码 minio.exe server data成功后…

内衣洗衣机什么牌子好又便宜?实力非凡机型深度测评

内衣裤这种小件的衣物紧密接触皮肤&#xff0c;更是接触特殊生理部位&#xff0c;所以&#xff0c;内衣裤对卫生标准有着特殊要求&#xff0c;现在很多人都是&#xff0c;把内衣裤放到家里的大型洗衣机和其他衣物混洗&#xff0c;你应该知道大型洗衣机由于长期清洗一些大件的衣…

【Linux】——期末复习题(十一)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

MySQL 8.0.35 企业版比社区版性能高出 25%?

前言 说实话&#xff0c;比较一下这两个 MySQL 发行版&#xff0c;并不会让我很兴奋。这是因为在我关于 MySQL 的记忆中&#xff0c;如果是谈代码库时&#xff0c;两个发行版之间没有真正的区别。 据我所知&#xff0c;企业版的差异在于附加的插件/组件&#xff0c;因此除非您…

简单版 git快速上手使用 clone项目 新建/切换分支 提交修改

Git是一个广泛使用的版本控制系统&#xff0c;允许多个用户跟踪文件的更改&#xff0c;并协作开发项目。 首先确定自己电脑已经安装了git&#xff0c;具体安装步骤请查找教程&#xff0c;应该不难。 以windows电脑为例&#xff0c;安装完后在搜索栏搜索git会出现 先解释一下这…

C# OpenVINO Nail Seg 指甲分割 指甲检测

目录 效果 模型信息 项目 代码 数据集 下载 C# OpenVINO Nail Seg 指甲分割 指甲检测 效果 模型信息 Model Properties ------------------------- date&#xff1a;2024-02-29T16:41:28.273760 author&#xff1a;Ultralytics task&#xff1a;segment version&#…

【GitHub】修改默认分支

GitHub的默认分支为main&#xff0c;但我们常常习惯使用master作为默认分支&#xff0c;那在GitHub上如何将master修改为默认分支呢&#xff1f; 全局修改 点击头像&#xff0c;选择菜单栏中的设置 输入master作为默认分支&#xff0c;然后执行updating即可&#xff01; 单项…