• [LeetCode] Find All Anagrams in a String


    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,在s中找出p的所有变位词的头索引。

    思路:用一维数组cnt存储p的所有字符及其出现次数(因为字符由ASCII码组成,所以申请一个大小为128的vector即可,用vector的索引值代表字符,vector的元素值代表字符出现次数),然后开始遍历s的每一位的同时遍历p,这时需要重新申请一个临时数组tmp来代替cnt,并对tmp的 值进行操作(访问过p的值后并让tmp的值减1)。最后将符合条件的头索引放入结果数组res中即可。

    这是一个蛮力迭代算法,优点是思路清晰,缺点是所用的时间复杂度较高。O(s * p)

    class Solution {
    public:
        vector<int> findAnagrams(string s, string p) {
            if (s.empty())
                return {};
            vector<int> res, cnt(128, 0);
            int sn = s.size(), pn = p.size(), i = 0;
            for (char c : p)
                cnt[c]++;
            while (i < sn) {
                bool success = true;
                vector<int> tmp = cnt;
                for (int j = i; j < i + pn; j++) {
                    if (tmp[s[j]]-- <= 0) {
                        success = false;
                        break;
                    }
                }
                if (success)
                    res.push_back(i);
                i++;
            }
            return res;
        }
    };
    // 543 ms

    通过上面的思路,很容易想到这是一个滑动窗口模型。

    首先建立一个哈希表m统计p中字符出现的次数。使用left和right表示滑动窗口的左右边界,cnt表示字符串p中需要匹配的字符个数。然后开始循环

    如果右边界字符已经在m中,说明该字符在p中出现,令cnt减1,然后m中该字符出现的次数也减1,右边界加1。

    如果此时cnt为0,则说明p中的字符都匹配成功,将左边界放入结果数组中。

    如果此时right与left之差等于p的长度, 说明此时应该去掉最左边的字符,如果这个字符在m中出现次数大于等于0,说明该字符是p中的字符。所以令cnt加1。

    class Solution {
    public:
        vector<int> findAnagrams(string s, string p) {
            if (s.empty()) 
                return {};
            vector<int> res, m(128, 0);
            int left = 0, right = 0, cnt = p.size(), n = s.size();
            for (char c : p) 
                m[c]++;
            while (right < n) {
                if (m[s[right++]]-- >= 1) 
                    cnt--;
                if (cnt == 0) 
                    res.push_back(left);
                if (right - left == p.size() && m[s[left++]]++ >= 0) 
                    cnt++;
            }
            return res;
        }
    };
    // 33 ms
  • 相关阅读:
    Redis集群搭建&访问
    Redis集群功能概述
    Redis多机功能之Sentinel
    Redis单机版安装与部署
    Redis多机功能之复制
    Redis多机功能介绍
    Hadoop JobHistory
    Hive基础之COALESCE用法
    junit组合模式应用
    Emmet
  • 原文地址:https://www.cnblogs.com/immjc/p/7655353.html
Copyright © 2020-2023  润新知