我在执行以下任务时遇到了问题.

一个正方形矩阵缺少11个字母,您必须将其替换.

每一行、每一列都包含"勇敢"这个词中的所有字母.

问题是,当我试图运行这段代码时,似乎有无限的递归, 这个节目永远不会结束.

我已经调试了两天,仍然找不到哪里出了问题.

public class Crossword {

    static Character[] letters = new Character[]{'B', 'R', 'A', 'V', 'E'};

    static boolean isFilled(char[][] matrix) {
        Set<Character> lettersSet = new HashSet<>(Arrays.asList(letters));

        // Check rows and columns simultaneously
        for (int i = 0; i < matrix.length; i++) {
            Set<Character> rowLetters = new HashSet<>();
            Set<Character> colLetters = new HashSet<>();

            for (int j = 0; j < matrix.length; j++) {
                rowLetters.add(matrix[i][j]);
                colLetters.add(matrix[j][i]);
            }

            if (!rowLetters.containsAll(lettersSet) || !colLetters.containsAll(lettersSet)) {
                return false;
            }
        }

        return true;
    }

    static boolean containsLetter(char[] row, char symbol) {
        for (char c : row) {
            if (c == symbol) {
                return true;
            }
        }

        return false;
    }

    static void fillMatrixBruteForce(char[][] matrix) {

        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix.length; j++) {

                if (matrix[i][j] == ' ') {

                    for (int k = 0; k < letters.length; k++) {
                        if (!containsLetter(matrix[i], letters[k])) {

                            matrix[i][j] = letters[k];
                            if (isFilled(matrix)) {
                                return;
                            } else {
                                fillMatrixBruteForce(matrix);
                            }

                        }
                    }
                    matrix[i][j] = ' ';
                }
            }
        }

    }

    static void print(char[][] matrix) {
        Arrays.stream(matrix).forEach(
                System.out::println
        );
    }

    public static void main(String[] args) {
        char[][] matrix = {
                {'B', 'R', 'A', 'V', 'E'},
                {' ', 'E', 'B', 'R', ' '},
                {' ', ' ', 'V', ' ', 'B'},
                {' ', 'B', 'R', ' ', ' '},
                {' ', ' ', 'E', 'B', ' '}
        };
        print(matrix);

        fillMatrixBruteForce(matrix);
        print(matrix);

推荐答案

该代码存在两个问题.

第一个是递归中的错误,导致倒数第二个空单元格永远不会被填充.

if (isFilled(matrix)) {
    return;
} else {
    fillMatrixBruteForce(matrix);
}

在第一种情况下,我们判断是否刚刚放置了最后一个字母.如果我们做到了,我们就会回来.这部分很好.

在第二种情况下,我们递归地调用自己,以查看此猜测是否会导致解决方案.然而,regardless of the outcome,我们表现得好像我们失败了,并推翻了我们的猜测.

为了解决这个问题,我们还判断递归是否成功,在这种情况下,我们返回:

if (isFilled(matrix)) {
    return;
} else {
    fillMatrixBruteForce(matrix);
    if (isFilled(matrix)) {
        return;
    }
}

(或者,fillMatrixBruteForce可以返回truefalse来表示它是成功还是放弃.这意味着我们不必第二次判断isFilled.)

第二个问题是性能.正如所写的那样,该算法非常慢.幸运的是,有一个简单的调整可以大幅加快速度.

对于上下文,有11个开放的单元格,每个单元格能够包含五个字母中的一个.这是48,828,125种不同的可能性需要判断.你真的不想强迫你的计算机递归地判断所有这些值,这意味着迅速放弃不可能的值是至关重要的.

您已经在一定程度上使用您的containsLetter方法做到了这一点.然而,这只判断给定的row是否包含该字母.这意味着许多明显不可能的组合从缝隙中溜走,完全是 brute 强迫的.通过添加第二个方法columnContainsLetter,并判断字母是否存在于either当前行或列(或两者)中,这将极大地减少我们被迫判断的可能性,并使算法在我的计算机上仅在几秒钟内运行.

Java相关问答推荐

当耗时的代码完成时,Circular ProgressIndicator显示得太晚

在URL类图中表示Java swing类

虚拟线程似乎在外部服务调用时阻止运营商线程

int Array Stream System. out. print方法在打印Java8时在末尾添加% sign

try 创建一个对象,使用它,然后使用一条语句将其存储为列表

在springboot 3中,当我调用api endpoint时,会出现404

在Java中,在单个逻辑行中连接列表和单个元素的正确方法是什么?

试着做一个2x2的魔方求解算法,我如何找到解路径(DFS)?

测试期间未执行开放重写方法

具有阻塞方法的开源库是否应该为执行提供异步选项?

如何解释Java中for-each循环中对Iterable的强制转换方法引用?

在JDK 1.8源代码中,为什么使用A-B 0来确定哪个更大,而不是A B?

未找到适用于响应类型[类java.io.InputStream]和内容类型[Text/CSV]的HttpMessageConverter

在向WebSphere中的文档添加元素时iText挂起

是否在settings.xml中使用条件Maven镜像?

JavaFX,GridPane:在GridPane的列中生成元素将保持所有列的宽度

如何在Struts2中使用操作类中的结果注释重定向到不同的命名空间

多线程、并发和睡眠未按预期工作

设置背景时缺少Android编辑文本下划线

在数组列表中找到对象后,未从数组中删除对象