【算法挨揍日记】day08——30. 串联所有单词的子串、76. 最小覆盖子串

简介: 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。例如,如果 words = ["ab","cd","ef"], 那么 "abcdef", "abefcd","cdabef", "cdefab","efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

30. 串联所有单词的子串

30. 串联所有单词的子串

题目描述:

给定一个字符串 s 和一个字符串数组 wordswords 中所有字符串 长度相同

s 中的 串联子串 是指一个包含  words 中所有字符串以任意顺序排列连接起来的子串。

  • 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef""abefcd""cdabef""cdefab""efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。

解题思路:

首先题目表示word的单词每个长度都一样,我们设为len

我们通过暴力解法来分析一下,当我们每次移动下标都下标可以+len

当然我们可能会从第一个字符开始判断也可以从第二个字符开始判断,因此第一个示例就有以下几种情况:

也就是有len种情况

我们可以利用滑动窗口+哈希表来解决这个问题

我们还需要使用一个代表有效个数的变量count

1.进窗口——hash2【in】++,当hash2<=hash1, count++(in为要进窗口的下标的字符串)

2. 判断——当m*len>right-left+1(m为s.size())

3.更新结果——ret.push一下

4.出窗口——当hash2<=hash1,count--,hash2【out】--,left+=len(out为要出窗口的下标的字符串)

这里我写了hash1.count(in)和hash1.count(out)是为了提升速度

解题代码:

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int>ret;
        unordered_map<string,int> hash1;
        for(auto& i:words) hash1[i]++;
        int len=words[0].size();int m=words.size();
        for(int i=0;i<len;i++)
        {
           unordered_map<string,int> hash2;
           int count=0;
           for(int left=i,right=i;right<s.size();right+=len)
           {
            string in=s.substr(right,len);
            hash2[in]++;
            if(hash1.count(in)&&hash2[in]<=hash1[in])count++;
            if(m*len<right-left+1)
            {
                string out=s.substr(left,len);
                if(hash1.count(out)&&hash2[out]<=hash1[out])count--;
                hash2[out]--;
                left+=len;
            }
            if(m==count)ret.push_back(left);
           }
        }
        return ret;
    }
};

76. 最小覆盖子串

76. 最小覆盖子串

题目描述:

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

解题思路:

本题还是滑动窗口+哈希

利用count和kind来解决这个问题(count为有效字符的个数,kind为种类个数)

1.进窗口——hash2[in]++,当in这个字符的个数达到要求,count++

2.判断——count==kind

3.更新结果——当length > right - left + 1,记录一下length和begin

4.出窗口

解题代码:

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> hash1;
        int kind = 0;//有效字符的种数
        for (auto& i : t) if (hash1[i]++ == 0)kind++;
        int count = 0;//有效字符个数(包括数量)的种类
        unordered_map<char, int>hash2;
        int length = INT_MAX;
        int begin=-1;
        for (int left = 0, right = 0; right < s.size(); right++)
        {
            char in = s[right];
            hash2[in]++;
            if (hash2[in] == hash1[in])count++;
            while(count == kind)
            {
                if (length > right - left + 1)
                {
                    length = right - left + 1;
                    begin=left;
                }
                char out = s[left];
                 if (hash2[out]--==hash1[out])count--;
                    out = s[++left];
            }
        }
        if(begin==-1)return "";
        string str=s.substr(begin,length);
        return str;
    }
};



相关文章
|
6月前
|
算法 索引
|
6月前
|
算法 索引
【算法挨揍日记】day09——35. 搜索插入位置、69. x 的平方根
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
62 0
|
2月前
|
人工智能 算法 测试技术
【字符串】【C++算法】828.统计子串中的唯一字符
【字符串】【C++算法】828.统计子串中的唯一字符
|
3月前
|
设计模式 算法 Java
【数据结构和算法】定长子串中元音的最大数目
这是力扣的 1456 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。又是一道滑动窗口的典型例题,可以帮助我们巩固滑动窗口算法。给你字符串s和整数k。 请返回字符串s中长度为k的单个子字符串中可能包含的最大元音字母数。 英文中的元音字母为(a,e,i,o,u)。
54 1
|
5月前
|
算法
代码随想录算法训练营第八天 | LeetCode 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串
代码随想录算法训练营第八天 | LeetCode 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串
44 0
|
6月前
|
算法 索引
【算法专题突破】滑动窗口 - 串联所有单词的子串(15)
【算法专题突破】滑动窗口 - 串联所有单词的子串(15)
17 0
|
6月前
|
算法
【算法挨揍日记】day12——153. 寻找旋转排序数组中的最小值、LCR 173. 点名
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
92 1
|
6月前
|
算法
【算法挨揍日记】day10——704. 二分查找、34. 在排序数组中查找元素的第一个和最后一个位置
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
331 0
|
6月前
|
存储 算法 索引
【算法挨揍日记】day07——904. 水果成篮、438. 找到字符串中所有字母异位词
题目描述: 你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而,农场的主人设定了
321 0
|
6月前
|
算法
【算法挨揍日记】day06——1004. 最大连续1的个数 III、1658. 将 x 减到 0 的最小操作数
1004. 最大连续1的个数 III 题目描述: 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。
367 1