[Leetcode学习-java]Word Search II(二维数组找相同字符串)

问题:

难度:Hard

说明:

给出二维数组arr,以及一个需要匹配的字符串数组strArr,然后在arr其中找到strArr的字符,需要是数组内连续的字符串,不限制方向,但是匹配时候只能用一次,题目确实比较绕,不过题意如此。

问题链接:https://leetcode.com/problems/word-search-ii/

相关算法:

P1002-过河卒:https://blog.csdn.net/qq_28033719/article/details/106261183

输入案例:

Input: 
board = [
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]
words = ["oath","pea","eat","rain"]
// o - a - t - h从(0,0) - (0,1) - (1,1) - (2,1)
// e - a - t从(3,1) - (2,1) - (1,1)
Output: ["eat","oath"]

我的代码:

相对来说比较困难,我一开始以为用Rabin-Karp算法,但是发现运算量会很大,而且也吃内存。

看提示就说用字典树,我开始用字典树给二维数组打(疯了),然后换成给strArr弄成字典树就好。

然后就是常见的图形搜索,用DFS,DFS用递归,二维数组DFS的坐标比较适合递归处理。

class Solution {
    static int x;
    static int y;
    // 结果集并且用hash去重
    HashSet<String> set;
    static char[][] board2;
    public List<String> findWords(char[][] board, String[] words) {
        // 将words全部存入字典树
        Tree root = new Tree();
        board2 = board;
        words2 = words;
        for(int i = 0;i < words.length;i ++) {
            String str = words[i];
            Tree tree = root;
            for(char ch : str.toCharArray()) {
                int index = ch - 'a';
                Tree next = tree.next[index] == null ? new Tree() : tree.next[index];
                tree.next[index] = next;
                tree = next;
            }
            tree.end = true;
            tree.index = i;
        }

        // 将二维数组遍历一遍
        set = new HashSet<String>();
        x = board2.length;
        y = board2[0].length;
        int c = x * y;
        for(int i = 0;i < x;i ++) {
            for(int j = 0;j < y;j ++) {
                int index = board2[i][j] - 'a';
                if(root.next[index] != null) {
                    // 为了不重复利用,设置参观表
                    boolean[][] visited = new boolean[x][y];
                    search(root,index, i,j,visited);
                }
            }
        }

        return new ArrayList<String>(set);
    }

    static String[] words2;
    // 方向,为了减少代码量
    static int[][] direct = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
    public void search(Tree root,int index, int i, int j, boolean[][] visited) {
        if(root.next[index] != null) {
            // 匹配到为true
            visited[i][j] = true;
            if(root.next[index].end) set.add(words2[root.next[index].index]);
            for(int[] arr : direct) {
                int x1 = i + arr[0];
                int y1 = j + arr[1];
                // 不约边,并且不重复浏览visited
                if(x1 >= 0 && x1 < x && y1 >= 0 && y1 < y && !visited[x1][y1]) {
                    search(root.next[index],board2[x1][y1] - 'a',x1,y1,visited);
                }
        }
            // 处理完成变为false
            visited[i][j] = false;
        }
    }
}

class Tree {
    Tree[] next = new Tree[26];
    boolean end = false;
    int index = 0;
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值