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

这个题用brute force是AC的,

优化的方案是sliding window,不过要遍历len(word in words)次


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
    	List<Integer> rst = new ArrayList<Integer>();
    	Map<String, Integer> map = new HashMap<String, Integer>();
    	int len = words[0].length(), n = words.length;
    	
    	for(String word : words)	map.put(word, map.containsKey(word) ? map.get(word) + 1 : 1);
    	
    	for(int i=0; i<=s.length()-n*len; i++) {
    		Map<String, Integer> temp = new HashMap<String, Integer>(map);
    		boolean f = true;
    		for(int j=0; j<n*len; j+=len) {
    			String key = s.substring(i+j, i+j+len);
    			if(!temp.containsKey(key))	{	f = false;	break; }
    			int nextVal = temp.get(key)-1;
    			if(nextVal < 0)				{	f = false;	break; }
    			temp.put(key, nextVal);
    		}
    		
    		if(f)	{rst.add(i);}
    	}
    	
    	return rst;
    }
}

package l30;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*
 * 之前写的暴力解法竟然能过。。。。。
 * 用2pointer,可以做到O(len(word in words) * len(s)),
 * 从s的0..len(word in words)开始分别走一遍sliding window
 */
class AC {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> ret = new ArrayList<Integer>();
        int n = s.length(), m = words[0].length();
        
        for(int i=0; i<m; i++) {

        	int need = words.length;
        	// Map还可以优化为不需要每次初始化,在结束当前循环前把p归到q上去
        	Map<String, Integer> map = new HashMap<String, Integer>();
        	for(String t : words) 	map.put(t, map.containsKey(t)?1+map.get(t):1);
        	
        	// sliding window
        	int p = i, q = i;
        	while(true) {
        		if(need == 0)	ret.add(p);
        		if(q+m > n)		break;
        		String t = s.substring(q, q+m);
        		
        		if(!map.containsKey(t)) {
        			// 出现words中没有的,
        			while(p != q) {
        				String tt = s.substring(p, p+m);
        				map.put(tt, map.get(tt) + 1);
        				p += m;
        				need ++;
        			}
        			q += m;
        			p = q;
        		} else if(map.get(t) == 0) {
        			// 多出个t
        			while(map.get(t) == 0) {
        				String tt = s.substring(p, p+m);
        				map.put(tt, map.get(tt) + 1);
        				p += m;
        				need ++;
        			}
        			map.put(t, map.get(t) - 1);
        			need --;
        			q += m;
        		} else {
        			// 正好需要这个string
        			map.put(t, map.get(t)-1);
        			need --;
        			q += m;
        		}
        	}
        }
        
        return ret;
    }
}

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> ret = new ArrayList<Integer>();
        int n = s.length(), m = words[0].length();
        Map<String, Integer> map = new HashMap<String, Integer>();
    	for(String t : words) 	map.put(t, map.containsKey(t)?1+map.get(t):1);
        
        for(int i=0; i<m; i++) {

        	int need = words.length;
        	
        	// sliding window
        	int p = i, q = i;
        	while(true) {
        		if(need == 0)	ret.add(p);
        		if(q+m > n)		break;
        		String t = s.substring(q, q+m);
        		
        		if(!map.containsKey(t)) {
        			// 出现words中没有的,
        			while(p != q) {
        				String tt = s.substring(p, p+m);
        				map.put(tt, map.get(tt) + 1);
        				p += m;
        				need ++;
        			}
        			q += m;
        			p = q;
        		} else if(map.get(t) == 0) {
        			// 多出个t
        			while(map.get(t) == 0) {
        				String tt = s.substring(p, p+m);
        				map.put(tt, map.get(tt) + 1);
        				p += m;
        				need ++;
        			}
        			map.put(t, map.get(t) - 1);
        			need --;
        			q += m;
        		} else {
        			// 正好需要这个string
        			map.put(t, map.get(t)-1);
        			need --;
        			q += m;
        		}
        	}
        	
        	while(p != q) {
        		String tt = s.substring(p, p+m);
				map.put(tt, map.get(tt) + 1);
				p += m;
        	}
        }
        
        return ret;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值