[英]ArrayList, List
當我試圖解決子集問題時,我寫了這樣的代碼:
public class Subsets {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, 0);
return list;
}
public void backtrack(List<List<Integer>> list, ArrayList<Integer>temp, int[] nums, int start){
list.add(temp);
for(int i = start; i<nums.length;i++){
temp.add(nums[i]);
backtrack(list, temp, nums, i++);
temp.remove(temp.size()-1);
}
}
}
輸出是
[[],[],[],[],[],[],[],[]]
但應該是正確的答案
[[3],[1],[2],[1,2,3],[1,3],[2,3],[1,2],[]]
當我改變這樣的“回溯”代碼時,答案是正確的:
public void backtrack(List<List<Integer>> list, List<Integer> temp, int[] nums, int start){
list.add(new ArrayList(temp));
for(int i = start; i<nums.length;i++){
temp.add(nums[i]);
backtrack(list, temp, nums, i+1);
temp.remove(temp.size()-1);
}
}
我的問題:為什么我需要編寫這樣的代碼:
public void backtrack(List<List<Integer>> list, List<Integer> temp, int[] nums, int start){
list.add(new ArrayList(temp));
而不是:
public void backtrack(List<List<Integer>> list, ArrayList<Integer> temp, int[] nums, int start){
list.add(temp);
這里:
list.add(new ArrayList(temp));
創建一個新的列表對象,與內容temp
在這個時間點。
而
list.add(temp);
只是增加了一個參照現有的temp
清單list
。
因此,在第二種情況下,當您稍后修改temp
也會影響list
的內容。
但除此之外:你應該更難以閱讀/理解代碼。 對該方法使用temp
參數沒有意義。 例如,您可以在方法內部將temp
局部變量。 無論如何,傳入列表是空的。 你沒有從使這個輸入參數獲得任何東西; 你只會增加困惑。
然后你改進你的命名 - 因為list
或temp
真的不會告訴讀者這些變量的意圖是什么。
list.add(temp)
將向列表添加對同一temp
對象的引用。 稍后,您將從中刪除元素,直到它為空,並且算法以包含對同一空列表的多個引用的列表結束。
使用new ArrayList(temp)
(或者更好的是 - 類型安全的new ArrayList<>(temp)
)將創建一個與temp
相同內容的新列表,所以稍后當你從temp
刪除元素時,這個列表不是影響。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.