[LeetCode] 30. Substring with Concatenation of All Words 解题思路 - Java

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in wordsexactly once and without any intervening characters.

For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

问题:给定一个字符串 s 和 一列单词 words 。找出 s 中所有满足下面条件的全部子字符串的开始下标:要求子字符串恰好由 words 的所有单词拼接而成,每个单词仅对应地出现一次。

由于 words 里面单词是无序的,目标子字符串的成员单词也是无序的,所以,考虑用 Hashtable 作为数据存储。

需要充分利用的两个题目条件:

1. 所有单词等长

2. 目标子字符串是由单词连续无中断地连接而成

根据上面两个条件,可以将 s 全部分割为长度为 length 的子字符串,共有 length 种分法。length 种分法会覆盖全部需要找的子字符串。

对于每一种分割,可以将长度为 length 的子字符串视为不再分割的单元,利用滑动窗口算法(Slide Window Algorithm),线性时间找到符合条件的目标子字符串,O(n/length) 复杂度,其中 n 为 s 的长度。一共有 length 种分发,则耗时 O(length * n/length) = O(n)。

算法实现思路

将 s 全部分割为长度为 length 的连续子串的方法,一共有 length 种。

对于每一种 k (0 <= k < length, 表示开始分割的起始下标 ) 有:

  以 k 为起始位置,长度为 length 子字符串即为一个待验证子串 subs

  左右指针指向首个 subs

  若右指针指向的 subs 是要找的 word, 并且已记录的次数小于需要找到的次数,则记录新找到一个 subs,右指针右移

  若右指针指向的 subs 是要找的 word,并且已记录的次数等于需要找到的次数, 则将左指针当前单词从记录中排除,并左指针右移,重复此操作直到从记录中排除一个右指针当前的 subs。使得 [ subs 已记录的次数小于需要找到的次数 ]。

  若右指针指向的 subs 不是要找的 word,则右指针右移,左指针指向右指针位置,并情况记录。

  若已找到的记录(左右指针内元素)恰好等于需要找到全部 words ,则保存左指针所在位置,即为一个需要找的下标。然后,将左指针当前元素从记录中排除,左指针右移。

实现代码

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

class Utility{

    /**
     * reset the value of matched result str_cnt_mch
     *
     * @param str_cnt_mch
     */
    public static void resetHashtable(Hashtable<String, Integer> str_cnt_mch){
        Set<Entry<String, Integer>> set = str_cnt_mch.entrySet();
        for (Entry<String, Integer> s_c : set){
            s_c.setValue(0);
        }
    }
}

public class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> res = new LinkedList<Integer>();

        Hashtable<String, Integer> str_cnt = new Hashtable<String, Integer>();
        Hashtable<String, Integer> str_cnt_mch = new Hashtable<String, Integer>();

        for (String wrd : words) {
            if (str_cnt.containsKey(wrd)) {
                str_cnt.put(wrd, str_cnt.get(wrd) + 1);
            } else {
                str_cnt.put(wrd, 1);
            }

            str_cnt_mch.put(wrd, 0);
        }

        int length = words[0].length();

        for (int k = 0; k < length; k++) {

            int lft = k;
            int rgh = k;

            Utility.resetHashtable(str_cnt_mch);
            int mchCnt = 0;

            while (rgh + length <= s.length()) {

                String subs = s.substring(rgh, rgh + length);

                if (str_cnt.containsKey(subs)) {

                    if (str_cnt_mch.get(subs) < str_cnt.get(subs)) {

                        str_cnt_mch.put(subs, str_cnt_mch.get(subs) + 1);
                        mchCnt++;

                        rgh += length;

                    } else {
                        // the number of subs in str_cnt_mch is the same as that
                        // in str_cnt

                        while (true) {

                            String subsl = s.substring(lft, lft + length);

                            str_cnt_mch.put(subsl, str_cnt_mch.get(subsl) - 1);
                            mchCnt--;

                            lft +=length;

                            if (subsl.equals(subs)) {
                                break;
                            }
                        }
                    }
                } else {
                    // subs is not a word in words
                    Utility.resetHashtable(str_cnt_mch);
                    mchCnt = 0;

                    rgh = rgh + length;
                    lft = rgh;
                }

                if (mchCnt == words.length){
                    res.add(lft);

                    String subsl = s.substring(lft, lft + length);
                    str_cnt_mch.put(subsl, str_cnt_mch.get(subsl) - 1);
                    mchCnt--;

                    lft = lft + length;
                }
            }
        }

        return res;
    }
}

参考资料:

Substring with Concatenation of All Words -- LeetCode, Code_Ganker, CSDN

时间: 2024-10-05 10:41:05

[LeetCode] 30. Substring with Concatenation of All Words 解题思路 - Java的相关文章

LeetCode 30 Substring with Concatenation of All Words (C,C++,Java,Python)

Problem: You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in wordsexactly once and without any intervening characters. For exam

[LeetCode] 030. Substring with Concatenation of All Words (Hard) (C++/Java)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 030. Substring with Concatenation of All Words (Hard) 链接: 题目:https://oj.leetcode.com/problems/substring-with-concatenation-of-all-words/ 代码(github):https://gi

leetCode 30.Substring with Concatenation of All Words (words中全部子串相连) 解题思路和方法

Substring with Concatenation of All Words You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without an

leetCode 30.Substring with Concatenation of All Words (words中所有子串相连) 解题思路和方法

Substring with Concatenation of All Words You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without an

Java [leetcode 30]Substring with Concatenation of All Words

题目描述: You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters. For exampl

[*leetcode 30] Substring with Concatenation of All Words

You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters. For example, given:S: "b

19.1.30 [LeetCode 30] Substring with Concatenation of All Words

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters. Example 1: Input

LeetCode 30 Substring with Concatenation of All Words(与所有文字串联子串)(*)

翻译 给定一个字符串S,一个单词的列表words,全是相同的长度. 找到的子串(多个)以s即每个词的字串联恰好一次并没有任何插入的字符所有的起始索引. 原文 You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word

LeetCode 30 Substring with Concatenation of All Words(确定包含所有子串的起始下标)

题目链接: https://leetcode.com/problems/substring-with-concatenation-of-all-words/?tab=Description 在字符串s中找到包含字符串数组words所有子串连续组合的起始下标(words中的子串排列顺序前后不计但是需要相连在s中不能存在其他字符) 参考代码 : package leetcode_50; import java.util.ArrayList; import java.util.Arrays; impo