2020年5月17日 星期日

Leetcode題解 Python & C#:五月挑戰DAY17 Find All Anagrams in a String

給一個字串 s 跟 非空字串 p 。要從 s 中找出所有 p 字謎的的起始位置。
(字謎是所有字母都出現一次,連續出現但順序可以變動)

如果順序不重要,那麼用 hashtable 記下哪些字母出現與次數及可。

從 s 開頭,依序匹配,是否在hashtable中及目前有可匹配的次數嗎?如果有,該字母的可匹配的次數 - 1,匹配長度 +1。
如果沒有,用匹配長度把最前方的已匹配字母放回hashtable所對應的次數,直到匹配或是匹配長度歸零為止。

如果匹配長度與 p 長度相同,則回推開始位置放入 result 中。

Python
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        count = Counter(p)
        match_len = 0
        p_len = len(p)
        result = []
        for i in range(len(s)):
            c = s[i]
            while match_len and (c not in count or count[c] == 0):
                count[s[i-match_len]] += 1
                match_len -= 1
            
            if c in count and count[c] > 0:
                count[c] -= 1
                match_len += 1
                if match_len == p_len:
                    result.append(i-p_len+1)
                        
        return result
C#
public class Solution {
    public IList FindAnagrams(string s, string p) {
        var count = new Dictionary();
        foreach(char c in p)
        {
            if(count.ContainsKey(c))
                count[c] += 1;
            else
                count[c] = 1;
        }
        var result = new List();
        int match_len = 0;
        for(int i = 0; i < s.Length; i ++)
        {
            char c = s[i];
            bool hasKey = count.ContainsKey(c);
            while(match_len > 0 && (!(hasKey) || count[c] == 0))
            {
                count[s[i - match_len]] += 1;
                match_len -= 1;
            }   
            if(hasKey && count[c] > 0)
            {
                match_len += 1;
                count[c] -= 1;
                if(match_len == p.Length)
                    result.Add(i - match_len + 1);
            }
        }
        return result;
    }
}