前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >leetcode472. Concatenated Words

leetcode472. Concatenated Words

作者头像
眯眯眼的猫头鹰
发布2019-11-04 11:04:16
4370
发布2019-11-04 11:04:16
举报

题目要求

Given a list of words (without duplicates), please write a program that returns all concatenated words in the given list of words. A concatenated word is defined as a string that is comprised entirely of at least two shorter words in the given array.

Example: Input: ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"]

Output: ["catsdogcats","dogcatsdog","ratcatdogcat"]

Explanation: "catsdogcats" can be concatenated by "cats", "dog" and "cats"; "dogcatsdog" can be concatenated by "dog", "cats" and "dog"; "ratcatdogcat" can be concatenated by "rat", "cat", "dog" and "cat". Note:

  1. The number of elements of the given array will not exceed 10,000
  2. The length sum of elements in the given array will not exceed 600,000.
  3. All the input string will only include lower case letters.
  4. The returned elements order does not matter.

现有一个无重复的字符串数组,要求找出所有所有拼接字符串,拼接字符串是指位于该数组中可以由数组中至少两个字符串拼接生成的字符串。

思路一:动态规划

已知短的字符串一定无法由长的字符串构成,因此可以将字符串排序,然后逐个判断当前字符串是否为拼接字符串,判断完毕后将该字符串加入字典中,作为下一个判断拼接字符串的可选子字符串。

这里的自底向上动态规划的思想用于判断是否为拼接字符串,即假设想要知道substring[0,i]是否可以拼接生成,并且已经知道substring[0,j]可以由其它字符串拼接而成,则只需要判断substring[i,j]是否可以为字典中的某个字符串即可。

代码如下:

    public List<String> findAllConcatenatedWordsInADict(String[] words) {
        if (words == null || words.length == 0) {return Collections.EMPTY_LIST;}
        Arrays.sort(words, Comparator.comparing(String::length));
        Set<String> wordSet = new HashSet<>();
        List<String> result = new ArrayList<>();
        for (String word : words) {
            if (find(wordSet, word)){
                result.add(word);
            }
        }
        return result;
    }
    
    public boolean find(Set<String> wordSet, String word) {
        if (wordSet.isEmpty()) {
            wordSet.add(word);
            return false;
        }
        boolean[] dp = new boolean[word.length()+1];
        dp[0] = true;
        for (int i = 1; i<=word.length() ; i++) {
            for (int j = 0 ; j<i ; j++) {
                if (!dp[j]){ continue;}
                if (wordSet.contains(word.substring(j, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        wordSet.add(word);
        return dp[word.length()];
    }

思路二:深度优先遍历

深度优先遍历的思想本质上和动态规划思想是类似的,这个是网上网友的答案,还做了另一层优化,即在最开始计算出整个数组中最短的字符串长度,并且以该字符串作为自字符串比对的起始长度。

代码如下:

    public List<String> findAllConcatenatedWordsInADict(String[] words) {
        List<String> res = new LinkedList<>();
        // corner case 
        if(words == null || words.length == 0) return res;
        
        // 1. Create HashSet
        Set<String> set = new HashSet<>();
        int minLen = Integer.MAX_VALUE;
        for(String word : words){
            if(word.length() > 0){
                set.add(word);
                minLen = Math.min(minLen, word.length());
            }            
        }
        
        for(String word : words){
            if(canCompose(word, 0, minLen, set)) res.add(word);
        }
        return res;
    }
    
    public boolean canCompose(String word, int start, int minLen, Set<String> set){
        for(int i = start + minLen; i <= word.length() - minLen; i++){
            if(set.contains(word.substring(start, i)) && (set.contains(word.substring(i)) || canCompose(word, i, minLen, set))) return true;
        }
        return false;
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目要求
  • 思路一:动态规划
  • 思路二:深度优先遍历
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档