关于ArrayList对象赋值问题

发布时间 2023-03-22 21:09:25作者: 夏雪冬蝉

今天在力扣上做了一个关于组合总和的题目,题目如下:

我实现的代码如下:

点击查看代码
class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> perList = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backtrace(candidates, target, 0);
        return result;

    }
    private void backtrace(int[] candidates, int target, int index) {
        if (target == 0) {
            result.add(perList);
            return;
        } else if (target < 0){
            return;
        }
        for (int i = index; i < candidates.length; i++) {
            perList.add(candidates[i]);
            target -= candidates[i];
            backtrace(candidates, target, i);
            target += candidates[i];
            perList.remove(perList.size()-1);
        }
        
    }
}

测试用例如下所示:

可以看到'result.size()=3',因此该代码是可以遍历到每一个候选组合的,但是传出的result数组却包含了三个空数组。然后我用debug调试了一下,发现每次更新perList数组,都会连带着更新result,从而删除result中的所有元素。

上网搜了一下,ArrayList对象直接赋值给另一个ArrayList对象属于浅拷贝。浅copy就是返回元素一样的ArrayList,但是元素本身并没有copy,如果原来元素的内容改变了,两个ArrayList内容都会随着改变(两部分公用元素)。深copy是指复制后两部分完全没有交集,各自有各自的元素。
改为下面代码,运行通过。

点击查看代码
class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> perList = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backtrace(candidates, target, 0);
        return result;

    }
    private void backtrace(int[] candidates, int target, int index) {
        if (target == 0) {
            //新建对象拷贝
            result.add(new ArrayList<>(perList));
            return;
        } else if (target < 0){
            return;
        }
        for (int i = index; i < candidates.length; i++) {
            perList.add(candidates[i]);
            target -= candidates[i];
            backtrace(candidates, target, i);
            target += candidates[i];
            perList.remove(perList.size()-1);
        }
        
    }
}
底层分析待我再研究研究