在网格中查找字符序列以形成字符串(一次向下或向右移动一步)

Finding a sequence of characters in a grid to form a string (moving down or right one step at a time)

提问人:Hector 提问时间:10/14/2018 更新时间:10/26/2018 访问量:221

问:

我得到了一个 n x n 的字符网格和一个字符串 s。我想找到一个路径(n 中的 (i, j) 对序列),以便它们形成一个拼写出 s 的路径。我可以从网格中的任意位置开始,但我只能在网格中向右或向下移动一步。

解决这个问题的有效方法是什么?我看过一个类似的问题,你可以向各个方向移动。但是,既然我们只能向右移动或向下移动,我们还能从中改进什么呢?

字符串 算法 矩阵 与语言无关

评论

0赞 m69 ''snarky and unwelcoming'' 10/14/2018
改进之处在于您不必跟踪访问的单元格,因为您不能绕圈子。

答:

0赞 Joris Schellekens 10/26/2018 #1

首先,让我们在图形结构中定义一个节点,我们将要使用。 就我们的目的而言,节点需要跟踪它的位置和它所代表的特征。

static class Node{

    int x;
    int y;
    char c;
    List<Node> adjecent = new ArrayList<>();

    public Node(int x, int y, char c){
        this.x = x;
        this.y = y;
        this.c = c;
    }

}

然后,我们需要一种简单的方法来构建一个节点网格,代表我们的字符网格。 我选择实现这一点,以便单个 String 对象可以表示整个网格,并且可以从该 String 构建网格。

public static Node[][] buildGraph(String s){
    String[] lns = s.split("\n");
    int M = lns.length;
    int N = lns[0].length();
    Node[][] out = new Node[M][N];
    for(int i=0;i<M;i++){
        for(int j=0;j<N;j++){
            out[i][j] = new Node(i,j,lns[i].charAt(j));
            if(i != 0)
                out[i-1][j].adjecent.add(out[i][j]);
            if(j != 0)
                out[i][j-1].adjecent.add(out[i][j]);
        }
    }
    return out;
}

现在是实际的算法。这(正如评论所建议的那样)是基于 BFS。 递归的入口点是以下方法,该方法检查网格中可能用作有效起始位置的所有节点。

private static void buildWord(Node[][] mtx, String target){
    char c = target.charAt(0);
    for(int i=0;i<mtx.length;i++){
        for(int j=0;j<mtx.length;j++){
            if(mtx[i][j].c == c){
                List<Node> tmp = new ArrayList<>();
                tmp.add(mtx[i][j]);
                buildWord(mtx[i][j], target, tmp);
            }
        }
    }
}

对于每个有效的起始位置,它调用方法“buildWord”,该方法尝试查找将拼写目标单词的路径的其余部分。 这是一个相对简单的 BFS。

private static void buildWord(Node start, String target, List<Node> path){
    if(path.size() > target.length()){
        return;
    } else if(path.size() == target.length()){
        String tmp = "";
        for(Node n : path)
            tmp += n.c;
        if(tmp.equals(target)){
            for(int i=0;i<path.size();i++)
                System.out.print("[" + path.get(i).x + ", " + path.get(i).y + "](" + path.get(i).c + ") --> ");
            System.out.print("\n");
        }
    } else {
        char nxtChar = target.charAt(path.size());
        for(Node n : start.adjecent){
            if(n.c == nxtChar){
                path.add(n);
                buildWord(n, target, path);
                path.remove(path.size() - 1);
            }
        }
    }
}

main 方法从 String 生成图形,然后尝试查找路径。 正在构建的图形表示

ABC
def
GHI

该算法试图找到“adeh”这个词

public static void main(String[] args){
    Node[][] matrix = buildGraph("abc\ndef\nghi");
    buildWord(matrix, "adeh");
}

它找到路径,并打印它

[0, 0](a) --> [1, 0](d) --> [1, 1](e) --> [2, 1](h) -->