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

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

思路:使用两个指针left和right维护一个窗口,left是窗口左边开始的位置,right是窗口右边的位置。使用dicMap作为一个字典,这个字典里面只存放在s中连续,且在words中存在的词汇。

如果没有形成窗口,那么left不变,right向后滑动。如果已经形成一个窗口,那么left和right就不断向后滑动,维持一个窗口,同时维持dicMap里面的元素。count==0代表dicMap字典里的元素和words相等。

Runtime: 22 ms   beats 99.77% of java submissions.

	public static List<Integer> findSubstring(String s, String[] words) {
		List<Integer> res = new ArrayList<>();
		int sLen = s.length(), wordLen = words[0].length(), windowLen = wordLen * words.length;
		HashMap<String, Integer> map = new HashMap<>();
		for (String word : words) map.put(word, map.getOrDefault(word, 0) + 1);
		for (int i = 0; i < wordLen; i++) {  // Run wordLen scans  
			HashMap<String, Integer> dicMap = new HashMap<>();//作为一个字典  
			for (int right = i, left = i, count = 0; right + wordLen <= sLen; right += wordLen) {
				if (left + windowLen > sLen) break;
				String word = s.substring(right, right + wordLen);
				if (!map.containsKey(word)) {
					dicMap.clear();
					count = 0;
					left = right + wordLen;
				} else {
					if (right - left == windowLen) { // Remove previous word of current window
						String preWord = s.substring(left, left + wordLen);// previous word
						left += wordLen;//left是窗口左边开始的位置,right是窗口右边的位置
						if (preWord.equals(word)) {
							if (count == 0) res.add(left);//res has contained left-wordLen
							continue;
						}
						int val = dicMap.get(preWord);
						dicMap.put(preWord, val - 1);
						if(val-1>=map.get(preWord)) count--;//Reduce count of exceeded word
					}
					dicMap.put(word, dicMap.getOrDefault(word, 0) + 1);//word放入字典中  
					if (dicMap.get(word) > map.get(word))
						count++;  //More than expected, increase count  
					if (count == 0 && left + windowLen == right + wordLen) {
						res.add(left);//if current window valid  
					}
				}
			}
		}
		return res;
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值