前言
这里记录一下陈菜菜的刷题记录,主要应对25秋招、春招
个人背景
211CS本+CUHK计算机相关硕,一年车企软件开发经验
代码能力:有待提高
常用语言:C++
系列文章目录
第29天 :第七章 回溯算法part03
`
文章目录
- 前言
- 系列文章目录
- 第29天 :第七章 回溯算法part03
- 一、今日任务
- 二、详细布置
- 93.复原IP地址
- 提示:
- 样例1:
- 思路
- 实战
- 78.子集
- 提示:
- 样例1:
- 思路
- 实战
- 踩坑
- 90.子集II
- 提示:
- 样例1:
- 样例2:
- 思路
- 实战
- 总结
一、今日任务
● 93.复原IP地址
● 78.子集
● 90.子集II
二、详细布置
93.复原IP地址
题目链接:力扣93
文章讲解:代码随想录
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 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 中的任何数字。你可以按 任何 顺序返回答案。
提示:
1 <= s.length <= 20
s 仅由数字组成
样例1:
输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
思路
这题很难,码一下,还没掌握。
实战
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;}
};
78.子集
题目链接:力扣78题链接
文章讲解:图文讲解
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的
子集
(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums 中的所有元素 互不相同
样例1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
思路
这题和组合问题类似,区别在于这个是先收集结果,再判断终止条件。
实战
class Solution {
public:vector<vector<int>> result;vector<int> vec;void backtracking(vector<int>& nums,int begin){result.push_back(vec);if(begin>=nums.size()){return ;}for(int i=begin;i<nums.size();i++){vec.push_back(nums[i]);backtracking(nums,i+1);vec.pop_back();}}vector<vector<int>> subsets(vector<int>& nums) {backtracking(nums,0);return result;}
};
踩坑
求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树。
90.子集II
题目链接:LeetCode90
文章讲解:图文讲解
题目描述
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的
子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
样例1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
样例2:
输入:nums = [0]
输出:[[],[0]]
思路
就是子集问题中重复元素的收集问题,参考LeetCode40
实战
class Solution {
public:vector<vector<int>> result;vector<int> vec;void backtracking(vector<int> &nums,int begin,vector<bool>& used){result.push_back(vec);if(begin>=nums.size()){return;}for(int i=begin;i<nums.size();i++){if(i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false){continue;}vec.push_back(nums[i]);used[i]=true;backtracking(nums,i+1,used);vec.pop_back();used[i]=false;}}vector<vector<int>> subsetsWithDup(vector<int>& nums) {vector<bool> used(nums.size(),false);backtracking(nums,0,used);return result;}
};
总结
今天主要学习了回溯的一系列操作,感觉是回溯还是我的薄弱区,好多问题做出来了但是不能细想,感觉逻辑还是理不清,但是套模板能做出来。
加油,坚持打卡的第29天。