为什么这里要用"res.add(new ArrayList<>(list));"?

3
class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> res = new ArrayList<>();
        if(root == null) return res;
        List<Integer> list = new ArrayList<>();
        helper(res, list, root, sum);
        return res;
    }
    public void helper(List<List<Integer>> res, List<Integer> list, TreeNode root, int sum){
        list.add(root.val);
        if(root.left == null && root.right == null){
            if(root.val == sum)
                res.add(new ArrayList<>(list));
        }
        if(root.left != null)
            helper(res, list, root.left, sum-root.val);
        if(root.right != null)
            helper(res, list, root.right, sum-root.val);
        list.remove(list.size()-1);
    }
}

我正在处理 Leetcode 113. 路径总和 II。这并不是关于问题本身,我想知道为什么在第13行不直接写res.add(list);而是写res.add(new ArrayList<>(list));

3个回答

6

使用 new ArrayList<>(list) 创建一个新的列表,其中包含 list 中的所有元素。这是必需的,因为在函数结束时调用 list.remove(list.size()-1); ,从而修改了 list 变量。

如果直接将 list 添加到 res 中,则 remove 调用也会修改 res

另一个相关的例子:

class MyClass {
    public int modify = 5;
}

class Test {
    public static void myFunction() {
        MyClass object = new MyClass();
        System.out.println(object.modify); // prints 5.

        ArrayList<MyClass> myList = new ArrayList<>();
        myList.add(object);

        object.modify = 800;
        for(MyClass item : myList) {
            System.out.println(item.modify); // prints 800.
        }
    }
}

2

new ArrayList<>(list)会复制list,这将确保元素存储在res中。

否则,在执行list.remove(list.size()-1)后,res中的元素将被删除。


0
在Java中,当我们将一个对象添加到集合中时,它作为引用被添加到主集合中。但是,如果我们稍后对该对象进行更改,这些更改也会反映在主集合中。
在这种情况下,我们需要删除'list'的最后一个元素以进行回溯,这会导致在'res'数组列表中也删除该元素。因此,我们必须创建'list'的深拷贝,即'res.add(new ArrayList<>(list))',以保持更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接