zoukankan      html  css  js  c++  java
  • leetcode425

    Given a set of words (without duplicates), find all word squares you can build from them.
    A sequence of words forms a valid word square if the kth row and column read the exact same string, where 0 ≤ k < max(numRows, numColumns).
    For example, the word sequence ["ball","area","lead","lady"] forms a word square because each word reads the same both horizontally and vertically.
    b a l l
    a r e a
    l e a d
    l a d y
    Note:
    1. There are at least 1 and at most 1000 words.
    2. All words will have the exact same length.
    3. Word length is at least 1 and at most 5.
    4. Each word contains only lowercase English alphabet a-z.

    DFS。with prune。
    最基础的DFS思想就是,在某一中间状态,前面几行已经被一些单词填了,我只管接下来这行填什么。我可以试着把单词本里的单词都一个个试着放在这一行,接着dfs,再回溯。
    但这种蛮力的dfs时间复杂度太高了,需要做一些提前prune。本题prune的基本思想是,行要依附于与列相等的规则。当我们最面几列的prefix是什么样已经定下来的时候,我们就可以强制要求后面几行的prefix是什么样,从而在以某些prefix开头的单词本dict根本不存在的时候,提前终结可能性。

    prune1: 填第l行的时候,要和第l列读着一样,而第l列已经有了前面一些prefix了,读出这个prefix,接下来可以插入第l行的候选单词也要以这个prefix开头。
    prune2: 填第l行第时候,不是所有上面以prefix开头的就可以了,还要进一步检查一下会不会坑队友。这一行填进去有0~l行了,那么l+1~n-1行的prefix也可以确定了,你确认一下是不是后面每行的prefix都还是有希望的,词典里有的。要是有任何一行被弄的没希望了,那你就算这行暂时加进去没问题,之后迟早一天注定会死,也还是就别加了。这个解法可以提前少掉后面几行(还没到注定要死行前)的好几种不同组合可能饿了。

    细节:
    1.额外写一个收集所有以某一prefix开头的单词的dict。类型<String, Set<String>>。注意所有原始单词都是以""前缀开头的。
    2.这题一些固定的一直要递归用到的变量很多,都放在参数列表里有点冗余,其实可以提出来做全局变量。dict, n

    实现:

    class Solution {
        public List<List<String>> wordSquares(String[] words) {
            List<List<String>> ans = new ArrayList<>();
            if (words == null || words.length == 0) {
                return ans;
            }
            
            int n = words[0].length();
            Map<String, Set<String>> dict = prefixDict(words);
            dfs(new ArrayList<String>(), ans, 0, n, dict);
            return ans;
        }
        
        private void dfs(List<String> crt, List<List<String>> ans, int l, int n, Map<String, Set<String>> dict) {
            if (l == n) {
                ans.add(new ArrayList<String>(crt));
                return;
            }
            
            String prefix = "";
            for (int i = 0; i < l; i++) {
                prefix += crt.get(i).charAt(l);
            }
            
            if (!dict.containsKey(prefix)) {
                return;
            }
            
            Set<String> set = dict.get(prefix);
            for (String s : set) {
                if (!canTry(l, s, crt, dict, n)) {
                    continue;
                }
                crt.add(s);
                dfs(crt, ans, l + 1, n, dict);
                crt.remove(crt.size() - 1);
            }
            
        }
        
        private Map<String, Set<String>> prefixDict(String[] words) {
            Map<String, Set<String>> map = new HashMap<>();
            map.put("", new HashSet<String>());
            for (String s : words) {
                String pref = "";
                map.get(pref).add(s);
                for (int i = 0; i < s.length(); i++) {
                    pref += s.charAt(i);
                    map.putIfAbsent(pref, new HashSet<String>());
                    map.get(pref).add(s);
                }
            }
            return map;
        }
        
        private boolean canTry(int l, String nextWord, List<String> crt, Map<String, Set<String>> dict, int n) {
            for (int j = l + 1; j < n; j++) {
                String prefix = "";
                for (int i = 0; i < l; i++) {
                    prefix += crt.get(i).charAt(j);
                }
                prefix += nextWord.charAt(j);
                if (!dict.containsKey(prefix)) {
                    return false;
                }
            }
            return true;
        }
    }
  • 相关阅读:
    python signal模块
    linux 下修改时间
    CentOS7关闭防火墙和SELinux
    centOS安装配置NFS
    python 调 java(胶水就是胶水)
    uuid
    python 最麻烦的时间有药了
    linux crontab
    Linux awk+uniq+sort 统计文件中某字符串出现次数并排序
    trove taskmanger api
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9644282.html
Copyright © 2011-2022 走看看