leetcode--Substring with Concatenation of All Words

本文介绍了一种利用滑动窗口解决字符串匹配问题的方法。通过示例解释如何找到字符串中由给定单词列表组成的子串的所有起始索引。文章详细讲解了算法实现过程,并附带Java代码。

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

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 example, given:
s"barfoothefoobarman"
words["foo", "bar"]

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

思路:思路是使用滑动窗口来解决问题,首先要找到起始位置,因为题目例如“barfoothefoobarman”,["foo","bar"],要查找的字符串长度为3,那么假设从开头开始找,我们就按顺序找bar,foo,the,foo,bar,man,然后在从第二个开始找,arf,oot,hef,oob,arm,再从三个开始找,rfo,oth,efo,oba,rma,然后从第四个开始找,这是我们就会发现其实已经重复了,也就是从第一个开始找,已经包含了从第四个开始找的内容,所以我们会在代码中看到,最外层循环是3

然后每次循环是这样的,我们从起始位置,每次获取三个字符作为字符串,并且检验是否是我们要找的字符串,如果是,修改记录(说明找到了一个);如果不是,就要移动起始位置

就算我们找到了要找的一个字符串,它也可能是多余的,例如我们之前已经找到了foo,但是下一个还是foo,超出的我们要找的foo数目,这时就要移动其实位置,直到记录中的foo数目小于或等于要找的数目,再重新设置其实位置

当我们找齐了所以字符串,保存当前起始位置,然后再去除窗口的第一个记录,接着继续向右查找

[java]  view plain  copy
  1. public class Solution {  
  2.     public List<Integer> findSubstring(String s, String[] words) {  
  3.         List<Integer> result = new ArrayList<Integer>();  
  4.         if(s==null || s.length()==0 || words==null || words.length==0)    
  5.             return result;  
  6.         Map<String,Integer> map = new HashMap<String,Integer>();   
  7.         for(int i=0;i<words.length;i++){//初始化map  
  8.             if(map.containsKey(words[i])){  
  9.                 map.put(words[i],map.get(words[i])+1);  
  10.             }else{  
  11.                 map.put(words[i],1);  
  12.             }          
  13.         }         
  14.         int word_size = words[0].length();          
  15.         for(int i=0;i<word_size;i++){//注意,这里循环字符串长度即可  
  16.             Map<String,Integer> findmap = new HashMap<String,Integer>();//用于记录当前字符串收集情况  
  17.             int count = 0;//当前收集个数  
  18.             int start = i;//当前起始index  
  19.             for(int j=i;j<=s.length()-word_size;j+=word_size){//从当前起始index开始到能容纳一个字符串的位置,j表示字符串的起始坐标               
  20.                 String word = s.substring(j, j+word_size);//获取当前字符串               
  21.                 if(map.containsKey(word)){                    
  22.                     if(!findmap.containsKey(word)){  
  23.                         findmap.put(word, 1);                         
  24.                     }else{                        
  25.                         findmap.put(word, findmap.get(word)+1);                       
  26.                     }  
  27.                     if(findmap.get(word)>map.get(word)){//滑动窗口                         
  28.                         while(findmap.get(word)>map.get(word)){//移动窗口直到消除多出来的字符串  
  29.                             String str = s.substring(start, start+word_size);  
  30.                             if(findmap.containsKey(str)){  
  31.                                 findmap.put(str, findmap.get(str)-1);  
  32.                                 if(findmap.get(str)<map.get(str))    
  33.                                     count--;  
  34.                             }  
  35.                             start += word_size;//重定位起始位置  
  36.                         }  
  37.                     }else{  
  38.                         count++;  
  39.                     }  
  40.                     if(count==words.length){//找齐                  
  41.                         result.add(start);  
  42.                         String temp = s.substring(start,start+word_size);    
  43.                         if(findmap.containsKey(temp))//去除第一个    
  44.                             findmap.put(temp,findmap.get(temp)-1);  
  45.                         count--;//数目减少1  
  46.                         start += word_size;//重定位起始位置  
  47.                     }  
  48.                 }else{//如果不是要找的字符串  
  49.                     count = 0;  
  50.                     start = j+word_size;//重定位起始位置  
  51.                     findmap.clear();  
  52.                 }                 
  53.             }                         
  54.         }          
  55.         //System.err.println(result);  
  56.         return result;  
  57.     }     

原文链接http://blog.youkuaiyun.com/crazy__chen/article/details/45625013

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值