首页 > 其他分享 >[leetcode 30 串联所有单词的子串 10ms]

[leetcode 30 串联所有单词的子串 10ms]

时间:2024-06-08 10:21:44浏览次数:25  
标签:map ch int 30 length str new 10ms leetcode

算法复杂度 o(1):

  • 复杂最坏复杂度 是 o(s.length) 和 o(m*total)的最大值
    码代码速度要变快,变量,算法要先想清楚

import java.util.*;

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        m = words[0].length();
        n = words.length;

        cnt = new HashMap<>();

        int total = 0;
        for (String word : words) {
            cnt.put(word, cnt.getOrDefault(word, 0) + 1);
            total += word.length();
        }

        List<Integer> ans = new LinkedList<>();
        // map[j]<str> 表示从[i,i+total -1]足要求的string的要求的出现各个位置
        map = new HashMap[m];
        int[] dp = new int[s.length()];
        for (int i = 0; i < dp.length;i++) {
            dp[i] = i + 1;
        }
        for (int i = 0; i < m; i++) {
            if (i + total > s.length()) {
                break;
            }
            boolean find = true;
            map[i] = new HashMap<String, LinkedList<Integer>>();
            for (int j = i + total - 1; j >= i + m - 1; j = j - m) {
                String str = s.substring(j - m + 1, j + 1);
                int num = cnt.getOrDefault(str, 0);
                int occur = map[i].getOrDefault(str, new LinkedList<>()).size();
                if (num > occur) {
                    // exist, 并且出现次数少
                    map[i].putIfAbsent(str, new LinkedList<>());
                    // 记录开始位置
                    map[i].get(str).addFirst(j - m + 1);
                    dp[i + total - 1] = j - m + 1;
                } else {
                    find = false;
                    break;
                }
            }
            if (find) {
                ans.add(i);
            }
        }
        // 遍历后面的
        for (int j = m; j <= s.length() - total; j++) {
            int tail = j + total - 1;

            String str = s.substring(j - m + total, j + total);

            if (cnt.getOrDefault(str, 0) == 0) {
                // 当前字符串不被包含;
                dp[tail] = tail + 1;
                continue;
            }

            // 上一个最远的位置
            int leftmost = dp[j + total - 1 - m];
            // 上个满足要求
            while (!map[j % m].getOrDefault(str, new LinkedList<>()).isEmpty() && map[j % m].get(str).getFirst() < leftmost) {
                map[j % m].get(str).pollFirst();
            }

            if (leftmost == j - m) {
                // 当前位置的最远, 默认能到达
                int newMostleft = j;
                if (!map[j % m].get(str).isEmpty()) {
                    // 肯定会到达这里, 因为该str肯定会被前面包含
                    newMostleft = map[j % m].get(str).pollFirst();
                }
                map[j % m].get(str).add(tail - m + 1);
                if (newMostleft == j - m) {
                    // 相同
                    dp[tail] = j;
                    ans.add(j);
                } else {
                    // 不相同
                    dp[tail] = newMostleft + m;
                }
            } else {
                int num = map[j % m].getOrDefault(str, new LinkedList<>()).size();
                int all = cnt.get(str);

                map[j % m].putIfAbsent(str, new LinkedList<>());
                map[j % m].get(str).add(tail -m + 1);
                if (num == all) {
                    int entry = map[j % m].get(str).getFirst();
                    // 顺序
                    dp[tail] = entry + m;
                    map[j % m].get(str).pollFirst();
                }
                else {
                    // 更新为最
                    dp[tail] = leftmost;
                    if (tail - leftmost + 1  ==  total) {
                        ans.add(j);
                    }
                }
            }
        }
        return ans;
    }

    int n;
    int m;
    int k = 0;
    Map<String, Integer> cnt;
    Map<String, LinkedList<Integer>>[] map;

    public static void main(String[] args) {
        TreeSet<Integer> set;
        Solution solution = new Solution();
        List<Integer> ans = solution.findSubstring("aaa", new String[]{
                "a", "a"
        });
        System.out.println(ans);
    }
}

算法2, trie树匹配

import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        build(words);
        int n = words.length;
        this.words = words;
        int cnt = 0;
        for (String word : words) {
            cnt += word.length();
        }

        List<Integer> ans = new ArrayList<>();
        for (int i = 0; i <= s.length() - cnt; i++) {
            find = false;
            dfs(s, i, 0);
            if (find) {
                ans.add(i);
            }
        }
        return ans;
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        List<Integer> ans = solution.findSubstring("wordgoodgoodgoodbestword", new String[]{
                "word","good","best","good"
        });
        System.out.println(ans);
    }

    boolean find = false;
    String[] words;

    public void dfs(String s, int start, int depth) {
        if (find) {
            return;
        }
        if (depth == words.length) {
            find = true;
            return;
        }

        if (start == s.length()) {
            return;
        }

        char ch = s.charAt(start);
        int idx = ch - 'a';

        if (root[idx] == null) {
            return;
        }

        TrieNode node = null;
        while (start < s.length()) {
            node = node == null ? root[idx] : node.findChild(s.charAt(start));
            start++;
            if (node == null) {
                return;
            }
            while (node.indexList.isEmpty() && start < s.length()) {
                node = node.findChild(s.charAt(start++));
                if (node == null) {
                    return;
                }
            }
            if (node.indexList.isEmpty()) {
                return;
            }
            int index = node.indexList.get(node.indexList.size() - 1);
            node.indexList.remove(node.indexList.size() - 1);

            dfs(s, start , depth + 1);

            node.indexList.add(index);
            if (start == s.length()) {
                return;
            }
        }

    }


    class TrieNode {
        TrieNode[] children = new TrieNode[26];
        char ch;

        int idx;

        List<Integer> indexList;

        public TrieNode(char ch) {
            this.ch = ch;
            children = new TrieNode[26];
            this.idx = ch - 'a';
            indexList = new ArrayList<>();
        }

        public TrieNode addChild(char ch) {
            if (children[ch - 'a'] == null) {
                children[ch - 'a'] = new TrieNode(ch);
            }
            return children[ch - 'a'];
        }

        public TrieNode findChild(char ch) {
            return children[ch - 'a'];
        }

        public void terminal(int index) {
            indexList.add(index);
        }

        public boolean hasTerminal() {
            return indexList.isEmpty();
        }

    }

    TrieNode[] root = new TrieNode[26];

    public void build(String[] words) {
        for (int i = 0; i < words.length; i++) {
            buildTrie(words[i], i);
        }
    }

    public void buildTrie(String word, int index) {
        char ch = word.charAt(0);
        int idx = ch - 'a';
        if (root[idx] == null) {
            root[idx] = new TrieNode(ch);
        }
        TrieNode curr = root[idx];
        for (int i = 1; i < word.length(); i++) {
            curr = curr.addChild(word.charAt(i));
        }
        curr.indexList.add(index);
    }
}

标签:map,ch,int,30,length,str,new,10ms,leetcode
From: https://www.cnblogs.com/fishcanfly/p/18238367

相关文章

  • Q15 LeetCode54 螺旋矩阵
    1.和上一题主体部分一模一样,加了判断语句2. intm=matrix.length,n=matrix[0].length;二维数组的长度3.List得实例化  1classSolution{2publicList<Integer>spiralOrder(int[][]matrix){34List<Integer>ans=newArrayList<>(......
  • Q14 LeetCode59 螺旋矩阵
    1.二维数组声明  int[][]ans=newint[n][n];2. left<=right&&top<=bottom 跳出循环条件 1classSolution{2publicint[][]generateMatrix(intn){3int[][]ans=newint[n][n];4intnum=1;5inttop=0,bottom=n-1,left......
  • Q13 LeetCode76 最小覆盖子串
    1.难题2.need.containsKey(r)看hashmap中是否含有r3.明天再复盘一遍  1classSolution{2publicStringminWindow(Strings,Stringt){3if(s==null||s.isEmpty()||t==null||t.isEmpty()||s.length()<t.length())return"";4......
  • 解决Docker遇到error NU1301: Unable to load the service index for source https://
    解决Docker容器内无法通过HTTPS访问外部网络的问题在使用Docker构建.NET项目时,有时会遇到无法通过HTTPS访问外部网络的问题,导致dotnetrestore命令无法从NuGet源下载依赖项。本文将介绍一种通过修改Docker配置文件config.json来解决该问题的方法。问题描述在......
  • 程序员最应该在30岁之前明白的道理,来自一位33岁码农的顶级感悟!
    从去年开始,互联网就业状况恶劣,从业人员悲观情绪开始蔓延,好多同行都表示被降薪甚至裁员,正在找工作的也表示boss刷烂了都是已读不回。网上的信息真真假假大家自己甄别,我说说自己的一些现状跟观察,希望对大家有参考意义。我目前在广州一家一百多人的小公司,属于交通行业中的软件......
  • 代码随想录算法训练营第30天|回溯复习篇
    回溯基础理论1.回溯的本质是利用递归进行暴力搜索,将符和条件的结果集搜索出来2.回溯法常见的问题:组合问题:N个数里面按一定规则找出k个数的集合排列问题:N个数按一定规则全排列,有几种排列方式切割问题:一个字符串按一定规则有几种切割方式子集问题:一个N个数的集合里有多少符合......
  • 60款柯达Kodak电影胶片调色预设SP-3000扫描仪配置文件2383电影卷2393视频lut优质精选
    60款柯达Kodak电影胶片调色预设SP-3000扫描仪配置文件2383电影卷2393视频lut优质精选预设预设在精不在多,素材湾倾心提供优质精选预设并整理安装使用教学助你学习工作中提升效率,更多时间专心于优质创作。*包含内容:5组共60款柯达电影胶片调色预设1款柯达SP-3000扫描仪配置(XMP......
  • LeetCode 2559. 统计范围内的元音字符串数
    2559.统计范围内的元音字符串数给你一个下标从 0 开始的字符串数组 words 以及一个二维整数数组 queries 。每个查询 queries[i]=[li,ri] 会要求我们统计在 words 中下标在 li 到 ri 范围内(包含 这两个值)并且以元音开头和结尾的字符串的数目。返回一个整......
  • python自动化脚本:12306-火车票购票
    1.导包:importtimefromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.common.keysimportKeysfromselenium.webdriver.support.uiimportWebDriverWait2.选择浏览器驱动:这里选择的是Chromedriver=webdriver.Chrom......
  • Leetcode 300. 最长递增子序列
    https://leetcode.cn/problems/longest-increasing-subsequence/description/给你一个整数数组nums,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]是数组[0,3,1,6,2,2,7]的子序列。示......