Substring with Concatenation of All Words

本文探讨了如何使用滑动窗口算法解决字符串中连续子串拼接所有单词的问题,详细解释了题目的核心逻辑与实现步骤,包括如何避免重复计算和优化算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 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).

滑动窗口的神题。思路和 Minimum Window Substring 非常相似。

但是这个题tricky一点在于要发现,只要遍历 string  每个单词长度(K) 遍 就可以包含全部情况。

 

几个容易出错的地方在代码中有标注。

 

这题是要求 without intervening characters的。这里跟  Minimum Window Substring 要求不同。所以就导致了再一次遍历中存在着重新初始化的情况(map初始化)

这一点应该是可以提升的,毕竟每次遇见intervening string就重启一个大的map很耗时。如果可以只修复map被污染的部分会好些。

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

        if (words.length == 0){
            
            return res;
        }
        
        int wl = words[0].length();
        HashMap<String, Integer> MAP = new HashMap<String, Integer>();
        for(String word : words){
            if(MAP.containsKey(word))
                MAP.put(word,MAP.get(word)+1);
            else
                MAP.put(word,1);
        }
        int size = words.length;
        for(int start=0; start<wl; start++){
            HashMap<String, Integer> map = new HashMap<String, Integer>(MAP);
            int cnt = 0;
            int l = start;
            //i<= s.length() - wl   Notice the equal sign, alway try out examples to ensure it.
            for(int i=start; i<=s.length()-wl; i+=wl){
                String word = s.substring(i,i+wl);
                if(l > s.length() - wl*size)
                    break;
                if(map.containsKey(word)){
                    if( map.get(word) > 0){
                        map.put(word, map.get(word)-1);
                        cnt += 1;
                    }else if(map.get(word) == 0){
                        while(l<i && map.get(word) == 0){
                            String leftWord = s.substring(l,l+wl);
                            map.put(leftWord, map.get(leftWord)+1);
                            cnt -= 1;
                            l += wl;
                        }
                        i -= wl;
                    }
                }else{
                    l = i+wl;
                    cnt = 0;
                    map = new HashMap<String, Integer>(MAP);
                }
                //Notice: check cnt at the end instead of front. Otherwise can't check the instance happened at very end
                if(cnt == size){
                    res.add(l);
                }
            }
        }
        return res;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值