代码随想录算法训练营第二十八天 | 93.复原IP地址、78.子集、90.子集II

93.复原IP地址

题目链接:93.复原IP地址

有效 IP 地址 正好由四个整数(每个整数位于 0255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

  • 例如:"0.1.2.201" "192.168.1.1"有效 IP 地址,但是 "0.011.255.245""192.168.1.312""192.168@1.1"无效 IP 地址。

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

文章讲解/视频讲解:https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html

思路

这道题和分割回文串有相似之处,同样采用回溯来解决。回溯的横向遍历是确定每层的分隔位置,纵向遍历则是递归地确定下一个分隔的位置。

首先确定回溯函数的参数:代表当前分隔的组合path,当前遍历到的下标starti。

确定结束条件:当starti遍历到字符串s末尾,或组合中的元素个数达到了四个。其中若同时满足这两个条件,将组合中的元素合成一个IP地址,加入结果。

遍历:横向遍历确定每层的分隔位置,纵向遍历则递归地确定下一个分隔的位置。对于每个分隔位置,判断从starti到该位置能否构成一个合法的IP字段,如果是,则可以纵向递归地向下遍历。

C++实现

class Solution {
public:vector<string> results;vector<string> restoreIpAddresses(string s) {vector<string> path;backtracing(path, 0, s);return results;}void backtracing(vector<string>& path, int starti, const string& s){if(starti == s.size() || path.size() == 4){if(starti == s.size() && path.size() == 4){string tmp;for(int i = 0;i<path.size();i++){tmp += path[i];if(i < path.size() - 1) tmp += ".";}results.push_back(tmp);}return;}for(int j = starti;j<s.size() && j < starti + 3;j++){ // 剪枝if(isvalid(s, starti, j)){path.push_back(s.substr(starti, j - starti + 1));backtracing(path, j + 1, s);path.pop_back();}}}bool isvalid(const string& s, int left, int right){// 判断前导0if(s[left] == '0'){if(right > left) return false;}int num = stoi(s.substr(left, right - left + 1));return num >= 0 && num <= 255;}
};

78.子集

题目链接:78.子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

文章讲解/视频讲解:https://programmercarl.com/0078.%E5%AD%90%E9%9B%86.html

思路

利用回溯来处理,这里横向遍历是遍历加入当前元素和不加入当前元素两种情况,纵向遍历是递归地寻找下一个元素。

回溯函数的参数:当前已加入的元素集合path,当前遍历到的元素下标starti。

回溯函数的终止条件:很简单,starti等于nums.size(),即遍历到原数组末尾。

回溯函数的遍历:每一层的横向遍历,遍历判断加入当前元素和不加入当前元素两种情况,纵向遍历是递归寻找下一个元素。

看了卡哥的教程之后,知道了原来可以把子集问题想成收集树的所有节点。如下图,相当于在遍历这样一棵树的时候,将节点的值全部存入结果中。

在这里插入图片描述

C++实现

class Solution {
public:vector<vector<int>> results;vector<vector<int>> subsets(vector<int>& nums) {vector<int> path;backtracing(path, 0, nums);return results;}void backtracing(vector<int>& path, int starti, const vector<int>& nums){        if(starti == nums.size()){results.push_back(path);return;}// 不加入i元素backtracing(path, starti + 1, nums);// 加入i元素path.push_back(nums[starti]);backtracing(path, starti + 1, nums);path.pop_back();}
};// 另一种思路
class Solution {
public:vector<vector<int>> results;vector<vector<int>> subsets(vector<int>& nums) {vector<int> path;backtracing(path, 0, nums);return results;}void backtracing(vector<int>& path, int starti, const vector<int>& nums){   results.push_back(path);     if(starti == nums.size()){return;}for(int i = starti;i<nums.size();i++){path.push_back(nums[i]);backtracing(path, i + 1, nums);path.pop_back();}}
};

90.子集II

题目链接:90.子集II

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

文章讲解/视频讲解:https://programmercarl.com/0090.%E5%AD%90%E9%9B%86II.html

思路

采用和上题一样的,遍历整棵树,将树的节点存入结果中的思路。本题多了一点,需要去重。

去重的思路:先把原数组nums排好序,然后回溯函数的每一层在遍历时,判断当前遍历的值和上一个遍历的值是否相等,如果相等则跳过。

C++实现

class Solution {
public:vector<vector<int>> results;vector<vector<int>> subsetsWithDup(vector<int>& nums) {sort(nums.begin(), nums.end());vector<int> path;backtracing(path, 0, nums);return results;}void backtracing(vector<int>& path, int starti, const vector<int>& nums){results.push_back(path);if(starti == nums.size()) return;for(int i = starti;i<nums.size();i++){if(i > starti && nums[i] == nums[i - 1]) continue; // 去重path.push_back(nums[i]);backtracing(path, i + 1, nums);path.pop_back();}}
};

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

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

相关文章

小程序系列--1.小程序入门

一、小程序简介 1. 小程序与普通网页开发的区别 1. 运行环境不同 网页运行在浏览器环境中 小程序运行在微信环境中 2. API 不同 由于运行环境的不同&#xff0c;所以小程序中&#xff0c; 无法调用 DOM 和 BOM 的 API。 但是&#xff0c;小程序中可以调用微信环境提供的各种 …

【办公】百度网盘 Linux命令行方式使用

安装&#xff1a; pip install bypy登录&#xff1a; bypy info # 会给网页链接&#xff0c;用浏览器打开链接后会有一个授权码&#xff0c;复制授权码后粘贴到这里回车上传文件&#xff1a; bypy upload ./data下载文件&#xff1a; bypy downdir /运行时添加-v参数&#…

Nginx快速入门:worker、master进程的作用和热部署原理(十)

0. 引言 我们通过查询nginx进程&#xff0c;可以发现nginx有两个进程&#xff1a;worker和master。一个程序启动了两个进程&#xff0c;那么这两个进程的作用和区别是什么呢&#xff1f;nginx又是如何利用这两个进程进行工作的呢&#xff1f;nginx不停机热部署又是如何实现的&…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷⑤

2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷5 目录 需要竞赛软件包环境以及备赛资源可私信博主&#xff01;&#xff01;&#xff01; 2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷5 模块一 …

普中STM32-PZ6806L开发板(HAL库函数实现-读取内部温度)

简介 主芯片STM32F103ZET6&#xff0c;读取内部温度其他知识 内部温度所在ADC通道 温度计算公式 V25跟Avg_Slope值 参考文档 stm32f103ze.pdf 电压计算公式 Vout Vref * (D / 2^n) 其中Vref代表参考电压&#xff0c; n为ADC的位数&#xff0c; D为ADC输入的数字信号。 实现…

用实例证明函数是go语言的一等公民

概述 在软件编程语言设计中&#xff0c;如果一个实体支持所有通常对其他实体可用的操作&#xff0c;那么这个实体就被称为“一等公民”&#xff08;first-class functions&#xff09;。这些操作通常包括作为参数传递、从函数返回、修改并分配给变量等。很多编程语言都实现了将…

【数据库】MySQL锁

一、锁的基本概念 1、锁的定义 锁是协调多个进程或线程并发访问数据库资源的一种机制。 MySQL中的锁是在服务器层或者存储引擎层实现的&#xff0c;保证了数据访问的一致性与有效性。但加锁是消耗资源的&#xff0c;锁的各种操作&#xff0c;包括获得锁、检测锁是否已解除、…

前端适配750px设计稿

全局引入 (function(doc, win) {const docEl doc.documentElement,resizeEvt orientationchange in window ? orientationchange : resizeconst setFont function() {let clientWidth docEl.clientWidth;if (!clientWidth) return;if (clientWidth > 750) {docEl.styl…

中兴通讯5G-A场景突破成果显著,获得行业高度认可

近年来&#xff0c;中兴通讯持续发力5G-A场景&#xff0c;积极进行相关技术研发&#xff0c;为6G时代的到来铺路。2023年12月28日&#xff0c;在2024&#xff08;第二十届&#xff09;ICT行业趋势年会“ICT龙虎榜揭榜盛典”当中&#xff0c;中兴通讯获得“2023年度5G-A场景开拓…

springcloud Config配置中心

简介 服务意味着要将单体应用中的业务拆分成一个个子服务&#xff0c;每个服务的粒度相对较小&#xff0c;因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行&#xff0c;所以一套集中式的、动态的配置管理设施是必不可少的。 SpringCloud提供了ConfigS…

深入剖析pcap中的网络异常:TTL过期攻击、ARP中毒、TCP重传与重叠碎片等

网络流量数据包捕获是网络安全领域的重要部分&#xff0c;而pcap文件则是这一过程的常见载体。为了深入解析pcap文件中潜在的可疑网络流量&#xff0c;我们需要运用强大的网络安全威胁评估与审计工具。这些工具能够帮助我们捕捉、记录、检测和诊断网络中的数据传输问题&#xf…

软件测试|Django 入门:构建Python Web应用的全面指南

引言 Django 是一个强大的Python Web框架&#xff0c;它以快速开发和高度可扩展性而闻名。本文将带您深入了解Django的基本概念和核心功能&#xff0c;帮助您从零开始构建一个简单的Web应用。 什么是Django&#xff1f; Django 是一个基于MVC&#xff08;模型-视图-控制器&a…