java - 尝试复制矩阵时出现 ArrayIndexOutOfBoundsException

标签 java arrays algorithm

我正在制作一个根据字典检查单词的程序,该程序根据字典中的单词检查单词中的每个字母。 我想通过将每个差异保存在矩阵中来优化它,然后如果该单词有一些相同的字符,则将其复制到下一个单词,这样程序就不必重新计算所有内容。但是,在我当前的解决方案中,我得到了 ArrayIndexOutOfBoundsException,但我没有看到问题。

import java.util.LinkedList;
import java.util.List;
import java.util.Arrays;

public class ClosestWords {
    LinkedList<String> closestWords = null;

    static int [][] SaveVal;
    int closestDistance = -1;
    static String savedWord;
    static String savedWrongWord;

    int partDist(String w1, String w2, int w1len, int w2len, int [][] SaveVal) {

        if (w1len == 0) {
            //return w2len;
            //SaveVal[0][w2len] = w2len;
            return w2len;
        }
        else if (w2len == 0) {
            //return w1len;
            //SaveVal[w1len][0] = w1len;
            return w1len;
        }
        else if(SaveVal[w1len-1][w2len-1] != 0) {
            return SaveVal[w1len-1][w2len-1];
        }

        int res = partDist(w1, w2, w1len - 1, w2len - 1, SaveVal) +
                (w1.charAt(w1len - 1) == w2.charAt(w2len - 1) ? 0 : 1);
        int addLetter = partDist(w1, w2, w1len - 1, w2len, SaveVal) + 1;
        if (addLetter < res)
            res = addLetter;
        int deleteLetter = partDist(w1, w2, w1len, w2len - 1, SaveVal) + 1;
        if (deleteLetter < res)
            res = deleteLetter;
        SaveVal[w1len-1][w2len-1] = res;
        return res;
    }

    int Distance(String w1, String w2) {
        int simLetters = checkSim(w1, w2);
        //System.out.println(simLetters);
        if(simLetters > 0)  {
            //Reuse the old array used before
            int [][] tempVal = new int [w1.length()][w2.length()]; // w2.length()
            for(int i = 0; i < SaveVal.length; i++)  {

                for(int j=0; j < SaveVal[i].length; j++)  {
    ############### ERRROR HERE WHEN RUNNING PROGRAM ############
                    tempVal[i][j] = SaveVal[i][j];
                }
            }



            SaveVal = tempVal;
            return (partDist(w1, w2, w1.length(), w2.length(), SaveVal));
        } else {
            //Completly new word
            SaveVal = new int [w1.length()][w2.length()];
            return (partDist(w1, w2, w1.length(), w2.length(), SaveVal));
        }
    }
        /*SaveVal = new int [w1.length()][w2.length()];
        return (partDist(w1, w2, w1.length(), w2.length(), SaveVal));*/

    int checkSim(String w1, String w2)  {
        int counter = 0;
        if(savedWord == null || !savedWrongWord.equals(w1))  {
            return 0;
        }
        char[] char1 = savedWord.toCharArray();
        char[] char2 = w2.toCharArray();
        if(char1.length > char2.length) {
            for(int x = 0; x < char2.length; x++)  {
                if(char1[x] == char2[x])  {
                    counter++;
                }
            }
        }else {
            for(int x = 0; x < char1.length; x++)  {
                if(char1[x] == char2[x])  {
                    counter++;
                }
            }
        }
        return counter;
    }

    public ClosestWords(String w, List<String> wordList) {
        savedWrongWord = w;
        for (String s : wordList) {
            int dist = Distance(w, s);
            savedWord = s;
            if (dist < closestDistance || closestDistance == -1) {
                closestDistance = dist;
                closestWords = new LinkedList<String>();
                closestWords.add(s);
            }
            else if (dist == closestDistance)
                closestWords.add(s);
        }
    }

    int getMinDistance() {
        return closestDistance;
    }

    List<String> getClosestWords() {
        return closestWords;
    }
}

最佳答案

你遇到异常是因为 SaveVal 和 tmpVal 不使用相同的 w2。 在我的测试用例中:

        String w = "sa";
        List<String> arrays = new LinkedList<>();
        arrays.add("sdasfq");
        arrays.add("sad");
        ClosestWords words = new ClosestWords(w, arrays);
        System.out.println(words.getClosestWords());

SaveVal 是使用 w1="sa"和 w2="sdasfg"创建的。但是,当 w2 = "sad"时,不会再次创建 SaveVal。所以 SaveVal 是 int[2][7] 而 tmpVal 是 int[2][3]。

您只需使用 SaveVal 来加速方法 partDist 的执行。每次迭代 wordList 时都应该创建 SaveVal。我认为您不能重用不同 w2 之间的中间结果,例如“sdasfg”、“sad”。

因此,您可以删除字段 SaveVal,并在方法 Distance() 中将其声明为局部变量

    int Distance(String w1, String w2) {
        int SaveVal[][] = new int[w1.length()][w2.length()];
        return (partDist(w1, w2, w1.length(), w2.length(), SaveVal));
}

我无法理解方法 checkSim()。我认为这是多余的。 代码是:

import java.util.LinkedList;
import java.util.List;
import java.util.Arrays;

public class ClosestWords {
    LinkedList<String> closestWords = null;

//    int [][] SaveVal;
    int closestDistance = -1;
    static String savedWord;
    static String savedWrongWord;

    int partDist(String w1, String w2, int w1len, int w2len, int [][] SaveVal) {

        if (w1len == 0) {
            //return w2len;
            //SaveVal[0][w2len] = w2len;
            return w2len;
        }
        else if (w2len == 0) {
            //return w1len;
            //SaveVal[w1len][0] = w1len;
            return w1len;
        }
        else if(SaveVal[w1len-1][w2len-1] != 0) {
            return SaveVal[w1len-1][w2len-1];
        }

        int res = partDist(w1, w2, w1len - 1, w2len - 1, SaveVal) +
                (w1.charAt(w1len - 1) == w2.charAt(w2len - 1) ? 0 : 1);
        int addLetter = partDist(w1, w2, w1len - 1, w2len, SaveVal) + 1;
        if (addLetter < res)
            res = addLetter;
        int deleteLetter = partDist(w1, w2, w1len, w2len - 1, SaveVal) + 1;
        if (deleteLetter < res)
            res = deleteLetter;
        SaveVal[w1len-1][w2len-1] = res;
        return res;
    }

    int Distance(String w1, String w2) {
        int SaveVal[][] = new int[w1.length()][w2.length()];
        return (partDist(w1, w2, w1.length(), w2.length(), SaveVal));
    }


    public ClosestWords(String w, List<String> wordList) {
        savedWrongWord = w;
        for (String s : wordList) {
            int dist = Distance(w, s);
            savedWord = s;
            if (dist < closestDistance || closestDistance == -1) {
                closestDistance = dist;
                closestWords = new LinkedList<String>();
                closestWords.add(s);
            }
            else if (dist == closestDistance)
                closestWords.add(s);
        }
    }

    int getMinDistance() {
        return closestDistance;
    }

    List<String> getClosestWords() {
        return closestWords;
    }

    public static void main(String[] args) {
        String w = "sa";
        List<String> arrays = new LinkedList<>();
        arrays.add("sdasfq");
        arrays.add("sad");
        ClosestWords words = new ClosestWords(w, arrays);
        System.out.println(words.getClosestWords());
    }

}

关于java - 尝试复制矩阵时出现 ArrayIndexOutOfBoundsException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54443456/

相关文章:

java - 我想用鼠标输入在窗口上绘制像素

python - 继承和扩展 Python bytearray

c++ - iter_swap 可以专门化吗?

algorithm - 有没有一种通用的方法可以将明确的上下文无关文法转换为 LALR(1) 文法?

silverlight - 在 Silverlight 中计算选取框类型动画的速度

java - 在java中用另一个字符串替换字符串

java - 如何在android 10中获取图像的方向信息?

java - java bouncycaSTLe 验证时间戳 token

ruby - 替换索引与给定索引不匹配的数组中的元素

C 存储大数组