当前位置: 首页 > news >正文

Leetcode-回溯-子集型

78. 子集 - 力扣(LeetCode)

class Solution {
    private List<Integer> path=new ArrayList<>();
    private List<List<Integer>> ans=new ArrayList<>();
    private int []nums; 
    public List<List<Integer>> subsets(int[] nums) {
        this.nums=nums;
        dfs(0);
        return ans;
    }
    public void dfs(int i){
        if(i==nums.length){
            ans.add(new ArrayList(path));
            return ;
        }
        dfs(i+1);
        path.add(nums[i]);
        dfs(i+1);
        path.remove(path.size()-1);
    }
}

在 Java 中,List 是对象,直接传递 path 时,传递的是对象的引用(即内存地址),而不是当前路径的“快照”。这会导致所有添加到 ans 中的结果实际上都指向同一个 path 对象。当后续回溯修改 path 时(比如 path.remove(...)),所有已添加到 ans 中的结果也会跟着被修改!最终你会看到 ans 中的每个子集都是空的,因为它们最终都指向同一个被清空了的 path


通过一个具体例子理解问题:

假设 nums = [1,2,3],递归过程如下:

  1. 当递归到最深层(i == 3)时,path 为空,此时 ans.add(path)。此时 ans 中的第一个元素是 path 的引用。

  2. 回溯到上一层,path.add(3),然后再次递归到 i=3,此时 path = [3]ans.add(path)。此时 ans 中有两个元素,但它们都指向同一个 path 对象。

  3. 继续回溯,path.remove(3),此时 path 变回空列表,而 ans 中已有的两个元素(引用)也会看到这个变化,结果都变成空列表!

最终 ans 中的所有子集会因为共享同一个 path 对象而全部被清空。

恢复现场: 在递归到某一“叶子节点”(非最后一个叶子)时,答案需要向上返回,而此时还有其他的子树(与前述节点不在同一子树)未被递归到,又由于path为全局变量。若直接返回,会将本不属于该子树的答案带上去,故需要恢复现场。 恢复现场的方式为:在递归完成后 dfs(i+1); 后,进行与“当前操作”相反的操作,“反当前操作”。

131. 分割回文串 - 力扣(LeetCode)

这题其实还是有点不理解     先写个注释 mark一下

class Solution {
    private List<String> path=new ArrayList<>();
    private List<List<String>>ans=new ArrayList<>();
    private String s;
    public List<List<String>> partition(String s) {
        this.s=s;
        dfs(0,0);
        return ans;
    }
    public void dfs(int i,int start){
        // i表示当前选择的s的下标  当i等于s的长度时 说明已经分割完毕
        if(i==s.length()){
            // 将path的副本加入到答案中
            ans.add(new ArrayList<>(path));
            // 回溯继续选择其他的可能
            return;
        }
        // 这里注意很巧妙的判断 一开始写的是i==s.length()-1想要判断当i=size-1的时候必须分割
        // 但是其实应该写的i<size-1 这样就包含了上面的情况  并且按照之前的思路进行递归 可以选也可以不选
        if(i<s.length()-1){
            dfs(i+1,start);
        }
        // 选择:  首先选择的前提是回文字符串 因此传入检查一下
        if(check(start,i)){
            // 如果符合条件就使用substring加入
            path.add(s.substring(start,i+1));
            // 继续递归  选择s字符串中下标为i+1的  并且传入上一轮遍历完  start应该在的位置i+1
            dfs(i+1,i+1);
            //恢复现场
            path.remove(path.size()-1);
        }
    }
    public boolean check(int left ,int right){
        while(left<right){
            if(s.charAt(left++)!=s.charAt(right--))
            return false;
        }
        return true;
    }
}

相关文章:

  • 增量数据同步怎么做
  • Show、Hide和Setvisible的区别
  • 88.HarmonyOS NEXT 性能监控与调试指南:构建高性能应用
  • 神聖的綫性代數速成例題2. 行列式的性質
  • RAG数据嵌入和重排序:如何选择合适的模型
  • 软考系统架构师 — 3 操作系统
  • 【系统设置】安装CUDA Toolkit,提升本地大模型运行效率
  • 笔记:代码随想录算法训练营day48:739. 每日温度\496.下一个更大元素 I\503.下一个更大元素II
  • Unity小框架之单例模式基类
  • 吴恩达机器学习笔记复盘(六)梯度下降算法
  • 使用OpenResty(基于Nginx和Lua)优化Web服务性能
  • 【蓝图使用】绘制mesh顶点的法线
  • 中考英语之08主谓一致
  • 奇安信全流量(天眼)面试题
  • 基于CATIA二次开发的低音炮腔体容积精准计算技术详解
  • LLMs基础学习(五)模型微调专题(上)
  • 蓝桥杯刷题周计划(第三周)
  • Java 绘制图形验证码
  • 浏览器对一个资源设置了缓存,如何清除缓存,且后续请求不命中缓存
  • docker删除容器不成功问题
  • 网商银行2024年年报发布,客户资产管理规模超过1万亿
  • 国新办发布《关于新冠疫情防控与病毒溯源的中方行动和立场》白皮书
  • 浙商银行一季度净赚超59亿微增0.61%,非息净收入降逾22%
  • 对谈|李钧鹏、周忆粟:安德鲁·阿伯特过程社会学的魅力
  • 王毅出席金砖国家外长会晤
  • 众信旅游:去年盈利1.06亿元,同比增长228.18%