【问题标题】:int[] vs ArrayList<>() in memoization, dynamic programming in Javaint[] vs ArrayList<>() 在记忆中,Java 中的动态编程
【发布时间】:2021-03-24 15:26:18
【问题描述】:

我最近在 Youtube 上观看了一个动态编程教程,解释了动态编程,但导师解决了 JavaScript 中的问题。另一方面,我将 Java 用于数据结构和算法。在实施动态规划来解决问题时。我发现我在使用int[] 时得到了问题的解决方案,但在使用ArrayList&lt;Integer&gt; 时得到了错误的答案,因为不知何故,已经存储在 HashMap 中的 ArrayList 正在内部被修改。

问题: 编写一个函数 bestSum(targetSum, numbers),它接受一个 targetSum 和一个数字数组作为参数,并返回一个数组,其中包含加起来正好是目标总和的最短数字组合。
示例:
bestSum(7,new int[]{2,1,3}) => [3,3,1] //其他可能但没有答案:[2,2,2,1], [1,1 ,1,1,1,1,1], [2,2,1,1,1] 等
bestSum(100,new int[]{2,5,25}) => [25,25,25,25]

使用 int[] 的代码:

public class Persist {
    public static HashMap<Integer,int[]> memo = new HashMap<>();
    public static int[] bestSum(int n, int[] arr){
        if(memo.containsKey(n)){
            //System.out.printf("From memo: %d->"+ Arrays.toString(memo.get(n)) +"%n",n);
            return memo.get(n);
        }

        if(n==0)return new int[0];

        if(n<0)return null;

        int[] minn = null;

        for(int i = 0;i<arr.length;i++){
            
            //recursion
            var temp = bestSum(n-arr[i],arr);

            if(temp!=null){

                // ttemp is used to add arr[i] to the initial arr <<temp>>
                int[] ttemp = new int[temp.length+1];
                System.arraycopy(temp,0,ttemp,0,temp.length);
                ttemp[temp.length] = arr[i];
                temp = ttemp;

                if(minn==null||temp.length<minn.length){
                    minn = temp;
                }
            }
        }
        //System.out.println(n+": "+minn);
        memo.put(n,minn);
        //System.out.println(memo.get(n));
        return minn;
    }
    public static void main(String[] args){
        System.out.println(Arrays.toString(bestSum(7, new int[]{2,1,3})));
    }
}

使用 ArrayList 的代码:

public class Persist {
    public static HashMap<Integer,ArrayList<Integer>> memo = new HashMap<>();
    public static ArrayList<Integer> bestSum(int n, int[] arr){
        if(memo.containsKey(n)){
            //System.out.printf("From memo: %d->"+ memo.get(n)+"%n",n);
            return memo.get(n);
        }
        if(n==0)return new ArrayList<>();
        if(n<0)return null;
        ArrayList<Integer> minn = null;
        for(int i = 0;i<arr.length;i++){
            var temp = bestSum(n-arr[i],arr);
            if(temp!=null){
                temp.add(arr[i]);
                if(minn==null||temp.size()<minn.size()){
                    minn = temp;

                }
            }
        }
        //System.out.println(n+": "+minn);
        memo.put(n,minn);
        //System.out.println(memo.get(n));
        return minn;
    }
    public static void main(String[] args){
        System.out.println(bestSum(7,new int[]{2,1,3}));
    }
}

两个代码 sn-ps 之间的唯一区别是分别使用 int[]ArrayList&lt;Integer&gt;,但一个有效,另一个无效。我想知道为什么,谢谢。 Link to Youtube explanation of bestSum()

【问题讨论】:

  • 提醒我,当你做memo.put(n, minn);时你会得到一个深拷贝吗?
  • @Surt 我做了类似的事情,但仍然得到错误的答案。 memo.put(n,minn==null?null:new ArrayList&lt;&gt;(minn));

标签: java arrays algorithm arraylist data-structures


【解决方案1】:

很容易陷入记忆化和动态编程,而忘记了按引用传递和按值传递。这里要记住的关键区别是ArrayList 是通过引用传递的。

如果您调试并查看您的hashmap memo,您会看到int[] 的大小仅达到3,而在arraylist hashmap 中大多数值的大小为@987654329 @

我也有类似的问题:casting does not work on nested list object type and returns empty lists (List<List<Integer>>)

【讨论】:

  • 同样适用于 c++ 吗?
  • ArrayList 实现的 value 的 hashCode() 与键相同:5,6,7
  • @lordvidex 除非您指定引用,否则不会复制 C++,但除非定义了适当的复制构造函数,否则不会通过指针传播副本。
猜你喜欢
  • 2013-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2021-10-01
  • 2016-12-02
  • 1970-01-01
  • 2020-12-10
相关资源
最近更新 更多