【问题标题】:Why should we copy an ArrayList in some recursive alogrithms?为什么我们要在一些递归算法中复制一个 ArrayList?
【发布时间】:2023-03-04 04:12:01
【问题描述】:

http://oj.leetcode.com/problems/subsets-ii/

给定一个可能包含重复的整数集合 S,返回所有可能的子集。

注意:

* Elements in a subset must be in non-descending order.
* The solution set must not contain duplicate subsets.

例如, 如果 S = [1,2,2],则解为:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

答案是:

public class Solution {
   public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] num) {
       ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
       ArrayList<Integer> tmp = new ArrayList<Integer>();
       Arrays.sort(num);
       sub(num, 0, tmp, ans);
       return ans;        
   }

   public void sub(int[] num, int k, ArrayList<Integer> tmp, ArrayList<ArrayList<Integer>> ans) {
       ArrayList<Integer> arr = new ArrayList<Integer>(tmp);            
       ans.add(arr);       

       for (int i = k; i < num.length; i++) {
           if (i != k && num[i] == num[i-1]) continue;

           tmp.add(num[i]);
           sub(num, i+1, tmp, ans);
           tmp.remove(tmp.size()-1);
       }
   }
}

不知道为什么

 ArrayList<Integer> arr = new ArrayList<Integer>(tmp);            
 ans.add(arr);

但不是直接:

 ans.add(tmp);

【问题讨论】:

  • 您是否尝试过您认为应该做的事情并检查会发生什么?

标签: java algorithm arraylist


【解决方案1】:

如果您只想打印结果,因为您删除了在递归调用之后添加的任何元素,tmp 在函数的开头和结尾应该看起来完全相同,所以它不应该任何区别(您的方式将是首选,因为它不会在每一步复制ArrayList)。

但是当你将结果添加到ans时问题就来了。

如果您使用自己的方式,则只会有一个 ArrayList 浮动 - 您只需将其添加到 ans 多次。

请注意,将其添加到ans 实际上并不会创建它的副本,它只是将ArrayList 的引用添加到ans。因此,在添加后更改原始元素也会更改 ans 的元素。

Live demo showing the correct result by printing them out and the incorrect results in the returned array.

【讨论】:

    【解决方案2】:

    直接添加它会使 arr 包含/与 tmp 相同的 ArrayList 实例。在你的循环中,当你改变 tmp 时,你也会改变 arr,这不是你想要的过程。

    【讨论】:

      【解决方案3】:

      不使用的原因

       ans.add(tmp);
      

      由于 tmp 是一个方法参数,所以 java 通过值传递对 ArrayList 的引用。 所以tmp 实际上是对 List 的引用,而不是 List。

      所以你需要创建一个 ArrayList 对象并将该对象添加到ans

      ArrayList<Integer> arr = new ArrayList<Integer>(tmp);            
      ans.add(arr);   
      

      如果你使用ans.add(tmp),那么tmp指向的arrayList会被添加到ans中,如果后面代码中对tmp进行了任何修改,那么你添加到@987654327的元素的内容@ 也会改变,因为两者都指向同一个内存块

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-14
        • 2013-08-15
        • 2021-01-02
        • 2022-01-17
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多