算法2:滑动窗口(下)

打印 上一主题 下一主题

主题 556|帖子 556|积分 1668

水果成篮


两元素排空操作
窗口中存在元素交错情况,以是出窗口肯定要出干净!!!
  1. class Solution {
  2. public:
  3.     int totalFruit(vector<int>& fruits) {
  4.         unordered_map<int, int> hash; // 统计水果情况
  5.         int res = 0;
  6.         for (int left = 0, right = 0; right < fruits.size(); right++) {
  7.             hash[fruits[right]]++;  // 进窗口
  8.             while (hash.size() > 2) // 判断
  9.             {
  10.                 // 出窗口
  11.                 hash[fruits[left]]--;
  12.                 if (hash[fruits[left]] == 0)
  13.                     hash.erase(fruits[left]);
  14.                 left++;
  15.             }
  16.             res = max(right - left + 1, res);
  17.         }
  18.         return res;
  19.     }
  20. };
复制代码
优化:
  1. class Solution {
  2. public:
  3.     int totalFruit(vector<int>& fruits) {
  4.         int hash[100001] = {0}; // 统计水果情况
  5.         int res = 0;
  6.         for (int left = 0, right = 0, kinds = 0; right < fruits.size();
  7.              right++) {
  8.             if (hash[fruits[right]] == 0)
  9.                 kinds++;           // 维护水果种类
  10.             hash[fruits[right]]++; // 进窗口
  11.             while (kinds > 2)      // 判断
  12.             {
  13.                 // 出窗口
  14.                 hash[fruits[left]]--;
  15.                 if (hash[fruits[left]] == 0)
  16.                     kinds--;
  17.                 left++;
  18.             }
  19.             res = max(right - left + 1, res);
  20.         }
  21.         return res;
  22.     }
  23. };
复制代码
本领:数据有限的情况下,用数组比用容器快很多
找到字符串中所有字母异位词


  1. class Solution {
  2. public:
  3.     vector<int> findAnagrams(string s, string p) {
  4.         if (s.size() < p.size())
  5.             return {};
  6.         vector<int> res;
  7.         long long sum = 0;
  8.         for (auto e : p)
  9.             sum += (e - '0') * (e - '0') * (e - '0');
  10.         int left = 0, right = 0;
  11.         long long target = 0;
  12.         while (right < s.size()) {
  13.             target += (s[right] - '0') * (s[right] - '0') * (s[right] - '0');
  14.             while (target >= sum && left <= right) {
  15.                 if (target == sum && right - left == p.size() - 1)
  16.                     res.push_back(left);
  17.                 target -= (s[left] - '0') * (s[left] - '0') * (s[left] - '0');
  18.                 left++;
  19.             }
  20.             right++;
  21.         }
  22.         return res;
  23.     }
  24. };
复制代码
  1. class Solution {
  2. public:
  3.     vector<int> findAnagrams(string s, string p) {
  4.         if (s.size() < p.size())
  5.             return {};
  6.         int hash1[26] = {0};
  7.         for (auto e : p)
  8.             hash1[e - 'a']++;
  9.         vector<int> res;
  10.         int hash2[26] = {0};
  11.         int m = p.size();
  12.         for (int left = 0, right = 0, count = 0; right < s.size(); right++) {
  13.             char in = s[right];
  14.             if (++hash2[in - 'a'] <= hash1[in - 'a']) // 进窗口及维护count
  15.                 count++;
  16.             if (right - left + 1 > m) // 判断
  17.             {
  18.                 char out = s[left++];
  19.                 if (hash2[out - 'a']-- <= hash1[out - 'a'])
  20.                     count--; // 出窗口及维护count
  21.             }
  22.             // 结果更新
  23.             if (count == m)
  24.                 res.push_back(left);
  25.         }
  26.         return res;
  27.     }
  28. };
复制代码
串联所有单词的子串*




  1. class Solution {
  2. public:
  3.     vector<int> findSubstring(string s, vector<string>& words) {
  4.         int slen = s.size(), plen = words.size(), _size = words[0].size();
  5.         plen *= _size;
  6.         if (plen == 0 || slen < plen)
  7.             return {};
  8.         // 滑动窗口+哈希表
  9.         vector<int> res;
  10.         unordered_map<string, int> aCount;
  11.         for (auto& e : words)
  12.             aCount[e]++;
  13.         unordered_map<string, int> bCount;
  14.         int n = words[0].size();
  15.         while (n--) /// 执行n次滑动窗口
  16.         {
  17.             for (int left = n, right = n, count = 0; right + _size <= s.size();
  18.                  right += words[0].size()) {
  19.                 string in = s.substr(right, words[0].size());
  20.                 bCount[in]++;
  21.                 // if(aCount[in] && bCount[in] <= aCount[in])   count++;
  22.                 if (aCount.count(in) && bCount[in] <= aCount[in])
  23.                     count++;
  24.                 // 这里窗口的长度是right + len -left,
  25.                 // 也就是说窗口的长度已经大于words的总体长度
  26.                 if (right - left == words[0].size() * words.size()) {
  27.                     string out = s.substr(left, words[0].size());
  28.                     // 这里用[]会影响速度,用哈希的计数函数快一些
  29.                     // count函数的返回值是0或1
  30.                     // ,类似于bool值,表示其是否存在,而[]返回的是次数,就涉及到了查找,故花费时间较长
  31.                     if (aCount.count(out) && bCount[out] <= aCount[out])
  32.                         count--;
  33.                     // if(aCount[out] && bCount[out] <= aCount[out]) count--;
  34.                     bCount[out]--;
  35.                     left += words[0].size();
  36.                 }
  37.                 if (count == words.size())
  38.                     res.push_back(left);
  39.             }
  40.             bCount.clear();
  41.         }
  42.         return res;
  43.     }
  44. };
  45. ```cpp
  46. class Solution {
  47. public:
  48.     vector<int> findSubstring(string s, vector<string>& words) {
  49.         vector<int> result;
  50.         if (s.empty() || words.empty())
  51.             return result;
  52.         int word_length = words[0].length();
  53.         int num_words = words.size();
  54.         int total_length = word_length * num_words;
  55.         unordered_map<string, int> word_count;
  56.         for (const string& word : words) {
  57.             word_count[word]++;
  58.         }
  59.         for (int i = 0; i < word_length; ++i) {
  60.             int left = i, right = i;
  61.             unordered_map<string, int> window_count;
  62.             while (right + word_length <= s.length()) {
  63.                 string word = s.substr(right, word_length);
  64.                 right += word_length;
  65.                 if (word_count.find(word) != word_count.end()) {
  66.                     window_count[word]++;
  67.                     while (window_count[word] > word_count[word]) {
  68.                         string left_word = s.substr(left, word_length);
  69.                         window_count[left_word]--;
  70.                         left += word_length;
  71.                     }
  72.                     if (right - left == total_length) {
  73.                         result.push_back(left);
  74.                     }
  75.                 } else {
  76.                     window_count.clear();
  77.                     left = right;
  78.                 }
  79.             }
  80.         }
  81.         return result;
  82.     }
  83. };
复制代码
两段代码都是:哈希+滑动窗口,时间空间复杂度也一样,但是测试时间却减少了许多,可以对比一下第二段代码优于第一段代码的点在哪里?
最小覆盖子串*



  1. class Solution {
  2. public:
  3.     string minWindow(string s, string t) {
  4.         string res;
  5.         int hash[128] = {0};
  6.         int tt = 0; // 字符种类
  7.         for (char& e : t)
  8.             if (0 == hash[e]++)
  9.                 tt++;
  10.         int hash1[128] = {0};
  11.         int begin = -1, m = INT_MAX;
  12.         for (int left = 0, right = 0, count = 0; right < s.size(); right++) {
  13.             // 进窗口
  14.             char in = s[right];
  15.             if (++hash1[in] == hash[in])
  16.                 count++;
  17.             //  检查
  18.             while (count == tt) {
  19.                 //  更新
  20.                 if (right - left + 1 < m) {
  21.                     begin = left;
  22.                     m = right - left + 1;
  23.                 }
  24.                 //  出窗口
  25.                 char out = s[left++];
  26.                 if (hash1[out]-- == hash[out])
  27.                     count--;
  28.             }
  29.         }
  30.         if (begin != -1)
  31.             res = s.substr(begin, m);
  32.         return res;
  33.     }
  34. };
  35. //  "ADOBEC"
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

熊熊出没

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表