Ваш код представляет собой довольно стандартный рекурсивный поиск в глубину (DFS) для всех возможных подмножеств набора чисел в массиве nums
.
Когда я запускаю ваш код в том виде, как он есть, он прекрасно работает. Например, я называю это так:
Solution app = new Solution();
int[] nums = { 5, 2 };
List<List<Integer>> subsets = app.subsets(nums);
subsets.forEach(System.out::println);
Выход:
[]
[5]
[5, 2]
[2]
И вы совершенно правы: если в вспомогательной функции dfs
мы не создадим копию списка с new
, результат отобразится в виде списка пустых списков. Я попытался изменить первую строку dfs
на просто:
res.add(list);
Теперь результат того же вызова, что и выше, выглядит так:
[]
[]
[]
[]
И я скажу вам, что: это не просто 4 пустых списка. Это тот же пустой список, который печатается 4 раза.
Перейдите по этой ссылке, чтобы увидеть разницу.
Почему это так? В конце концов, как вы сказали, вспомогательный метод добавляет элементы в список в своем цикле:
list.add(nums[i]);
Без new
один и тот же список передается каждому рекурсивному вызову dfs
. Хотя элементы добавляются в этот список, они также снова удаляются из него:
list.remove(list.size()-1);
Таким образом, большую часть времени во время выполнения вашего кода, список результатов списков, res
будет содержать список с элементами в нем (один и тот же список несколько раз), в конце все элементы будут удалены из содержащийся список.
То, что new
делает, как вы знаете, берет копию списка. Таким образом, состояние списка, какие элементы он содержит, сохраняется: никакие элементы не будут удалены из копии, когда элементы будут удалены из исходного списка. Таким образом, ваш результат в конечном итоге содержит все разные списки и все элементы в них, которые были там, когда список был добавлен в результат.