簡體   English   中英

ArrayList,List

[英]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局部變量。 無論如何,傳入列表是的。 你沒有從使這個輸入參數獲得任何東西; 你只會增加困惑。

然后你改進你的命名 - 因為listtemp真的不會告訴讀者這些變量的意圖是什么。

list.add(temp)將向列表添加對同一temp對象的引用。 稍后,您將從中刪除元素,直到它為空,並且算法以包含對同一空列表的多個引用的列表結束。

使用new ArrayList(temp) (或者更好的是 - 類型安全的new ArrayList<>(temp) )將創建一個與temp相同內容的新列表,所以稍后當你從temp刪除元素時,這個列表不是影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM