LeetCode 438. Find All Anagrams

2019-02-20  本文已影响0人  njim3

题目

Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.

Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.

The order of output does not matter.

Example 1:
Input:  s: "cbaebabacd" p: "abc"
Output:  [0, 6]

Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".

Example 2:
Input:  s: "abab" p: "ab"
Output:  [0, 1, 2]

Explanation:
The substring with start index = 0 is "ab", which is an anagram of "ab".
The substring with start index = 1 is "ba", which is an anagram of "ab".
The substring with start index = 2 is "ab", which is an anagram of "ab".

解析

此题要求找出s串中和p串一致的所有位置,在匹配的过程中不要求一致,任何一个p串的排列组合在s串中有匹配即算是一个结果。
对于这种无序的题目,通常使用的方法是构建Hash,对比字符出现的次数进行匹配。本题要编写的过程中要注意,能提前剔除的情况要除去,否则会造成Time exceed limit。

代码(C语言)

bool is2HashEqual(int* sHash, int* pHash);
int* findAnagrams(char* s, char* p, int* returnSize) {
    if (!s || !p)
        return NULL;
    
    int sLen = (int)strlen(s), pLen = (int)strlen(p);
    if (sLen < pLen)
        return NULL;
    
    int* pHash = (int*)calloc(26, sizeof(int));
    int* sHash = (int*)calloc(26, sizeof(int));
    
    int* returnArr = (int*)calloc(sLen, sizeof(int));
    (*returnSize) = 0;
    
    for (int i = 0; i < pLen; ++i) {
        ++pHash[p[i] - 'a'];
        ++sHash[s[i] - 'a'];
    }
    
    for (int i = 0; i <= sLen - pLen; ++i) {
        if (i != 0) {
            ++sHash[s[i + pLen - 1] - 'a'];
        }
        
        if (is2HashEqual(sHash, pHash)) {
            returnArr[(*returnSize)++] = i;
        }
        
        --sHash[s[i] - 'a'];
    }
    
    free(pHash);
    free(sHash);
    
    return returnArr;
}

bool is2HashEqual(int* sHash, int* pHash) {
    for (int i = 0; i < 26; ++i) {
        if (sHash[i] != pHash[i])
            return false;
    }
    
    return true;
}

这里,笔者使用了滑动窗口的做法。先把最开始pLen长度的进行匹配,然后依次向后一个窗口,再次进行匹配。这里循环执行的长度<= sLen-pLen,这里需要有等于,边界情况要考虑到。

上一篇 下一篇

猜你喜欢

热点阅读