目录
LeetCode 93.复原IP地址
文章讲解:代码随想录
视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili
力扣题目:LeetCode 93.复原IP地址

思考:
提供的条件:一段数字字符串。
结果:求出所有符合要求的字符串。
主要求:把数字字符串分割成四个整数(用回溯来做)。(且每个整数之间的范围为0~255,当单个整数不为0时,不能有前置0,且分割整数之间要用.来隔开。)做一个函数来实现这个功能。
次要求:不能重新排序或删除字符串s中的任何数字。
进一步思考:既然是把一个字符串分割成多个符合要求的字符串,可以想到用的是回溯算法。那么回溯算法的三部曲:1.确定递归函数的返回值和参数。2.确定递归终止条件。3.单层搜索逻辑。大方向确定之后,最后对于每一个整数的范围大小做一个判断即可。
回溯三部曲:
1.确定递归的返回值和参数
private void backTrack(String s, int startIndex, int pointNum){}
2.确定递归的终止条件
if(pointNum == 3){
if(isValid(s, startIndex, s.length()-1)){
result.add(s);
}
}
3.单层搜索逻辑
//遍历宽度
for(int i = startIndex; i < s.length(); i++){
//判断是否符合条件
if(isValid(s, startIndex, i)){
//添加.号
s = s.substring(0, i + 1) + "." + s.substring(i + 1);
//记录分割点
pointNum++;
//向深度递归
backTrack(s, i + 2, pointNum);
//返回结果后,删除分割点
pointNum--;
//返回结果后删除.号
s = s.substring(0, i + 1) + s.substring(i + 2);
}else{
break;
}
}
代码如下(Java):
class Solution {
//接收结果集合
List<String> result = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
//做一个剪枝操作
if(s.length() > 12) return result;
backTrack(s, 0, 0);
return result;
}
/**
@param s
@param startIndex
@param pointNum 记录分割点
*/
private void backTrack(String s, int startIndex, int pointNum){
if(pointNum == 3){
if(isValid(s, startIndex, s.length()-1)){
result.add(s);
}
}
//遍历宽度
for(int i = startIndex; i < s.length(); i++){
//判断是否符合条件
if(isValid(s, startIndex, i)){
//添加.号
s = s.substring(0, i + 1) + "." + s.substring(i + 1);
//记录分割点
pointNum++;
//向深度递归
backTrack(s, i + 2, pointNum);
//返回结果后,删除分割点
pointNum--;
//返回结果后删除.号
s = s.substring(0, i + 1) + s.substring(i + 2);
}else{
break;
}
}
}
private Boolean isValid(String s, int start, int end){
if(start > end){
return false;
}
//对单个整数不为0且前置为0进行处理
if(s.charAt(start) == '0' && start != end){
return false;
}
int num = 0;
//判断单个整数是否符合范围
for(int i = start; i <= end; i++){
if(s.charAt(i) > '9' || s.charAt(i) < '0'){
return false;
}
num = num * 10 + (s.charAt(i) - '0');
if(num > 255){
return false;
}
}
return true;
}
}
LeetCode 78.子集
文章讲解:代码随想录
视频讲解:回溯算法解决子集问题,树上节点都是目标集和! | LeetCode:78.子集_哔哩哔哩_bilibili
力扣题目:LeetCode 78.子集

思路:首先返回整数数组中的子集可以想到要用回溯算法,把数组中所有可能的子集看成一棵倒立的树,接下来要收集所有可能的子集就是要收集树的每一个节点的值。
回溯三部曲:
1.确定递归返回值和参数
private void subsetsHelper(int[] nums, int startIndex){}
2.确定递归终止条件
if(startIndex >= nums.length) return;
3.单层搜索逻辑
for(int i = startIndex; i < nums.length; i++){
path.add(nums[i]);
subsetsHelper(nums, i+1);
path.removeLast();
}
代码如下Java:
class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
subsetsHelper(nums, 0);
return result;
}
private void subsetsHelper(int[] nums, int startIndex){
result.add(new ArrayList<>(path));
if(startIndex >= nums.length) return;
for(int i = startIndex; i < nums.length; i++){
path.add(nums[i]);
subsetsHelper(nums, i+1);
path.removeLast();
}
}
}
LeetCode 90.子集II
文章讲解:代码随想录
视频讲解:回溯算法解决子集问题,如何去重?| LeetCode:90.子集II_哔哩哔哩_bilibili
力扣题目:LeetCode 90.子集II

回溯三部曲:
1.确定递归的返回值和参数
private void backTracking(int[] nums, int startIndex){}
2.确定递归的终止条件
if(startIndex >= nums) return;
3.单层搜索逻辑
//遍历树的宽度
for(int i = startIndex; i < nums.length; i++){
//对树层上进行去重
if(i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;
//表示对应的元素已经使用过
used[i] = true;
//收集元素path上
path.add(nums[i]);
//递归深度
backTracking(nums, i+1);
//下面两条代码都是进行回溯的操作
used[i] = false;
path.removeLast();
}
代码如下(Java):
class Solution {
List<List<Integer>> resList = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums) {
used = new boolean[nums.length];
Arrays.fill(used, false);
Arrays.sort(nums);
backTracking(nums, 0);
return resList;
}
private void backTracking(int[] nums, int startIndex){
//收集树中每一个节点的值
resList.add(new ArrayList<>(path));
if(startIndex >= nums) return;
//遍历树的宽度
for(int i = startIndex; i < nums.length; i++){
//对树层上进行去重
if(i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;
//表示对应的元素已经使用过
used[i] = true;
//收集元素path上
path.add(nums[i]);
//递归深度
backTracking(nums, i+1);
//下面两条代码都是进行回溯的操作
used[i] = false;
path.removeLast();
}
}
}
文章介绍了如何使用回溯算法解决LeetCode上的93号问题(复原IP地址)和78、90号问题(子集)。核心思想是通过确定递归返回值和参数、设定递归终止条件以及实现单层搜索逻辑。在复原IP地址问题中,重点是确保每个分割的整数在0-255范围内且无前导0。子集问题则涉及收集所有可能的子集,需要处理去重的情况。
1082

被折叠的 条评论
为什么被折叠?



