LeetCode 题解(112): 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).

题解:

用HashMap简单粗暴比较。唯一的优化是当s中出现重复单词且超过在dict中的数量时,可以将指针向前移动到该重复单词的下一个单词处。

C++版:

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        int length = words[0].length() * words.size();
        vector<int> results;
        if(s.length() < length)
            return results;
        
        unordered_map<string, int> occurrences;
        for(int i = 0; i < words.size(); i++) {
            if(occurrences.find(words[i]) == occurrences.end())
                occurrences.insert(pair<string, int>(words[i], 1));
            else
                occurrences[words[i]]++;
        }
        
        for(int i = 0; i <= s.length() - length; i++) {
            string temp = s.substr(i, length);
            test(results, occurrences, temp, (int)words[0].length(), (int)words.size(), i);
        }
        return results;
    }
    
    void test(vector<int>& results, unordered_map<string, int> occurrences, string& s, int l, int n, int& pos) {
        for(int i = 0; i < n; i++) {
            string current = s.substr(i * l, l);
            if(occurrences.find(current) != occurrences.end()) {
                if(occurrences[current] > 0)
                    occurrences[current]--;
                else {
                    pos = pos + s.find(current) + l - 1;
                    return;
                }
            } else {
                return;
            }
        }
        results.push_back(pos);
    }
};

Java版:

public class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> results = new ArrayList<Integer>();
        if(words.length * words[0].length() > s.length())
            return results;
        
        Map<String, Integer> count = new HashMap<>();
        for(int i = 0; i < words.length; i++) {
            if(count.containsKey(words[i]))
                count.put(words[i], count.get(words[i]) + 1);
            else
                count.put(words[i], 1);
        }
        
        for(int i = 0; i <= s.length() - words.length * words[0].length(); i++) {
            Map<String, Integer> local = new HashMap<String, Integer>(count);
            int j;
            for(j = 0; j < words.length; j++) {
                String current = s.substring(i + j * words[0].length(), i + (j + 1) * words[0].length());
                if(local.containsKey(current)) {
                    if(local.get(current) > 0)
                        local.put(current, local.get(current) - 1);
                    else {
                        i = s.indexOf(current, i) + words[0].length() - 1;
                        break;   
                    }
                } else {
                    break;
                }
            }
            if(j == words.length)
                results.add(i);
        }
        return results;
    }
}

Python版:

import copy

class Solution:
    # @param {string} s
    # @param {string[]} words
    # @return {integer[]}
    def findSubstring(self, s, words):
        results = []
        if len(s) < len(words) * len(words[0]):
            return results
            
        count = {}
        for i in words:
            if i in count:
                count[i] += 1
            else:
                count[i] = 1
        i = 0
        while i <= len(s) - len(words) * len(words[0]):
            local = copy.copy(count)
            j = 0
            while j < len(words):
                current = s[i + j * len(words[0]) : i + (j + 1) * len(words[0])]
                if current in local:
                    if local[current] > 0:
                        local[current] -= 1
                        j += 1
                    else:
                        i = s.find(current, i) + len(words[0]) - 1
                        break
                else:
                    break
            if j == len(words):
                results.append(i)
            i += 1
            
        return results
                    


你可能感兴趣的:(Algorithm,LeetCode,面试题)