走重复路或不走重复路问题

214 阅读2分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。

给定一个char[][] matrix,也就是char类型的二维数组,再给定一个字符串word,可以从任何一个某个位置出发,可以走上下左右,能不能找到word?

设定1:可以走重复路的情况下,返回能不能找到 比如,word = "zoooz",是可以找到的,z -> o -> o -> o -> z,因为允许走一条路径中已经走过的字符

设定2:不可以走重复路的情况下,返回能不能找到 比如,word = "zoooz",是不可以找到的,因为允许走一条路径中已经走过的字符不能重复走

char[][] m = {
                { 'a', 'b', 'z' }, 
                { 'c', 'd', 'o' }, 
                { 'f', 'e', 'o' }
             } 

一、分析

f(i,j,k):从m[i][j]这个字符出发,能不能找到str[k...]这个后缀串,当k==str.length时,说明匹配的是空串,也返回true(能找到)

二、实现

    // 可以走重复路
    // 从m[i][j]这个字符出发,能不能找到str[k...]这个后缀串
    public static boolean canLoop(char[][] m, int i, int j, char[] str, int k) {
        if (k == str.length) {
            return true;
        }
        if (i == -1 || i == m.length || j == -1 || j == m[0].length || m[i][j] != str[k]) {
            return false;
        }
        // 不越界!m[i][j] == str[k] 对的上的!
        // str[k+1....]
        boolean ans = false;
        if (canLoop(m, i + 1, j, str, k + 1) || canLoop(m, i - 1, j, str, k + 1) || canLoop(m, i, j + 1, str, k + 1)
                || canLoop(m, i, j - 1, str, k + 1)) {
            ans = true;
        }
        return ans;
    }

    // 不能走重复路
    // 从m[i][j]这个字符出发,能不能找到str[k...]这个后缀串
    public static boolean noLoop(char[][] m, int i, int j, char[] str, int k) {
        if (k == str.length) {
            return true;
        }
        if (i == -1 || i == m.length || j == -1 || j == m[0].length || m[i][j] != str[k]) {
            return false;
        }
        // 不越界!也不是回头路!m[i][j] == str[k] 也对的上!
        m[i][j] = 0;
        boolean ans = false;
        if (noLoop(m, i + 1, j, str, k + 1) || noLoop(m, i - 1, j, str, k + 1) || noLoop(m, i, j + 1, str, k + 1)
                || noLoop(m, i, j - 1, str, k + 1)) {
            ans = true;
        }
        m[i][j] = str[k];
        return ans;
    }

三、总结

走重复路优化:

  1. 记忆化缓存(杀缓存)
  2. 严格位置的动态规划

不能走重复路:

  1. 标记
  2. 恢复