【问题标题】:Implementing edit distance method using recursion results in object heap error使用递归实现编辑距离方法导致对象堆错误
【发布时间】:2012-11-27 20:12:47
【问题描述】:
    private static int editDistance(ArrayList<String> s1, ArrayList<String> s2) {
        if (s1.size()==0) {
            return s2.size();
        } 
        else if (s2.size()==0) {
            return s1.size();
        } 
        else {
            String temp1 = s1.remove(s1.size()-1);
            String temp2 = s2.remove(s2.size()-1);
            if (temp1.equals(temp2)) {
                return editDistance((ArrayList<String>)s1.clone(),(ArrayList<String>)s2.clone());
            } else {
                s1.add(temp1);
                int first = editDistance((ArrayList<String>)s1.clone(),(ArrayList<String>)s2.clone())+1;
                s2.add(temp2);
                s1.remove(s1.size()-1);
                int second = editDistance((ArrayList<String>)s1.clone(),(ArrayList<String>)s2.clone())+1;
                s2.remove(s2.size()-1);
                int third = editDistance((ArrayList<String>)s1.clone(),(ArrayList<String>)s2.clone())+1;
                if (first <= second && first <= third ) {
                    return first;
                } else if (second <= first && second <= third) {
                    return second;
                } else {
                    return third;
                }
            }
        }
    }

例如输入可以是["div","table","tr","td","a"]["table","tr","td","a","strong"],对应的输出应该是2

我的问题是当任一输入列表的大小太大时,例如,列表中有 40 个字符串,程序将生成 can't reserve enough space for object heap 错误。 JVM 参数为-Xms512m -Xmx512m。我的代码可能需要这么多堆空间吗?还是因为我的代码中的逻辑错误?

编辑:无论是否克隆列表,这种递归方法似乎都不起作用。有人可以帮助估计为我工作所需的总堆内存吗?我想这会令人震惊。无论如何,我想我必须改用动态编程方法。

【问题讨论】:

  • 乍一看我会说你的递归不会终止
  • 这是由于克隆列表。最好传递两个索引并在每次递归调用时适当地递增它们。
  • @Jochen 好吧,我已经测试了小长度的列表,例如 10,它可以工作。
  • can't reserve enough space for object heap 建议您没有内存不足 - 但您尝试保留大量空间。你有什么环境?是嵌入式系统吗?
  • @khachik 好主意!我会试试的。

标签: java recursion heap-memory dynamic-programming edit-distance


【解决方案1】:

在每次递归调用您的方法之前,您 clone() 每个 ArrayList 实例。这实质上意味着您每次调用都会获得整个列表及其内容的另一个副本 - 它可以轻松地添加到非常大的内存量以实现大递归深度。

您应该考虑使用List#sublist() 而不是clone(),或者甚至在您的方法中添加参数以将索引传递给一组初始List 对象。

【讨论】:

  • 无论是否克隆列表,这种递归解决方案似乎无论如何都不起作用,导致相同的堆错误。我想我会改用动态编程技术。
猜你喜欢
  • 2013-10-13
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 2012-07-24
  • 2012-08-08
  • 2010-11-07
  • 2020-07-21
  • 1970-01-01
相关资源
最近更新 更多