[刷题记录Day 28]Leetcode组合之回溯算法

No.1

题目

复原IP地址

思路

  • 写一个函数,判断是否是有效的IP地址元素(即两点之间的部分是否合法)
  • 这是一个分割问题
  • 回溯法

递归分析

  1. 全局变量:``List pathList result`
  2. 返回值:空,参数:原始字符串,startIndex
  3. 终止条件
    1. 字符串用光了,且path有4个元素,存储结果,返回
  4. 单层递归逻辑
    1. 处理当前节点
    2. 如果合法,且path不超过4个成员,进入下层递归
    3. 回溯,抛出当前节点

代码

public boolean judger(String str) {
int len = str.length();
// 超过3位
if (len > 3)
return false;
// 有先导0
if (len > 1 && str.indexOf("0") == 0)
return false;
// 超过255
if (Integer.parseInt(str) > 255)
return false;
return true;
}
private List<String> path;
private List<String> result;
public void restoreHelper(String s, int startIndex) { // before, not included
if (startIndex >= s.length() && path.size() == 4) {
StringBuilder sb = new StringBuilder();
for (String value : path) {
sb.append(value);
sb.append(".");
}
sb.deleteCharAt(sb.length() - 1); // 去掉最后多余的"."
result.add(sb.toString());
}
for (int i = startIndex; i < s.length(); i++) {
String subStr = s.substring(startIndex, i + 1);
if (path.size() < 4) { // 保证path不超过4个元素
path.add(subStr);
if (judger(subStr))
restoreHelper(s, i + 1);
path.remove(path.size() - 1);
}
}
}
public List<String> restoreIpAddresses(String s) {
path = new ArrayList<>();
result = new ArrayList<>();
restoreHelper(s, 0);
return result;
}

No.2

题目

子集

思路

  • 回溯法
  • 首先要对数组排序
  • 和之前的组合收集叶子节点不同,这里要收集树的所有节点,所以递归退出的地方没有任何操作,而在每次节点更新后,同步更新result

代码

private List<Integer> path;
private List<List<Integer>> result;
public void subsetHelper(int[] nums, int startIndex) {
if (startIndex >= nums.length)
return;
for (int i = startIndex; i < nums.length; i++) {
path.add(nums[i]);
result.add(new ArrayList<>(path));
subsetHelper(nums, i + 1);
path.remove(path.size() - 1);
}
}
public List<List<Integer>> subsets(int[] nums) {
path = new ArrayList<>();
result = new ArrayList<>();
result.add(new ArrayList<>()); // 先塞一个[]
Arrays.sort(nums);
subsetHelper(nums, 0);
return result;
}

No.3

题目

子集 II

思路

  • 回溯法
  • 稍微精简了代码
  • 输入存在重复元素,要排序后去重
    • 这里的“去重”,是树的同一层上去重

代码

private List<Integer> path;
private List<List<Integer>> result;
public void subsetHelper(int[] nums, int startIndex) {
result.add(new ArrayList<>(path));
if (startIndex >= nums.length)
return;
for (int i = startIndex; i < nums.length; i++) {
// 去除重复结果
if (i > startIndex && nums[i] == nums[i - 1])
continue;
path.add(nums[i]);
subsetHelper(nums, i + 1);
path.remove(path.size() - 1);
}
}
public List<List<Integer>> subsetsWithDup(int[] nums) {
path = new ArrayList<>();
result = new ArrayList<>();
Arrays.sort(nums);
subsetHelper(nums, 0);
return result;
}
posted @   喜欢毛绒绒的番茄子  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示