首页 > 其他分享 >力扣 leetcode 438. 找到字符串中所有字母异位词

力扣 leetcode 438. 找到字符串中所有字母异位词

时间:2022-12-03 16:25:46浏览次数:50  
标签:子串 窗口 异位 字母 力扣 438 字符串 滑动 leetcode

问题描述

给定两个字符串 sp,找到 s 中所有 p异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

提示:

  • 1 <= s.length, p.length <= 3 * 10^4
  • sp 仅包含小写字母

示例

示例 1:

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

示例 2:

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

解题思路

根据题目要求,我们需要在字符串 s 寻找字符串 p 的异位词。因为字符串 p 的异位词的长度一定与字符串 p 的长度相同,所以我们可以在字符串 s 中构造一个长度为与字符串 p 的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量;当窗口中每种字母的数量与字符串 p 中每种字母的数量相同时,则说明当前窗口为字符串 p 的异位词。

具体来说,我们用一个 map 统计 p 中每个字母出现的次数,然后滑动窗口内每个字母都要出现在 p 中,且个数不超过 p 中相应字母的个数。我们在遍历的时候主要会遇到以下情况。

字符可以添加进滑动窗口

如果 s[i] 出现在 p 中,且滑动窗口内 s[i] 的个数小于 p 中相应字符的个数,则可以将 s[i] 添加进滑动窗口。

字符出现在 p 内,但滑动窗口内该字符已满

此时,我们假设 s[i'] == s[i]i' 是滑动窗口内字符 s[i] 第一次出现时在 s 中的下标。我们将 i'i' 之前的元素从滑动窗口中弹出,并将 s[i] 添加进滑动窗口,此时还要根据弹出的元素数量更新当前滑动窗口内元素的数量。

字符不在 p

此时,应该将滑动窗口的起始位置放在 i + 1 处,并将滑动窗口内的元素全部弹出。

根据上述分析,实现如下代码:

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        if(s.size() < p.size()){ // 如果s的长度小于p的长度,直接返回空
            return {};
        }
        vector<int> res;
        map<char, int> cnt; // 记录每个单词的频率
        for(int i = 0; i < p.size(); i++){
            cnt[p[i]]++;
        }
        int windowSize = p.size();
        int cursor = 0;
        for(int i = 0; i <= s.size(); i++){ // 通过滑动窗口遍历s
            for(int j = i + cursor; j < s.size() && cursor < windowSize; j++){ // cursor指向滑动窗口内下一个元素的位置
                if(cnt.count(s[j])){ // 判断s[j]是否出现在p内
                    if(cnt[s[j]]){ // s[j]在p内,且还可以再添加进滑动窗口
                        cnt[s[j]]--;
                        cursor++;
                        if(cursor == windowSize){ // 判断滑动窗口是否已满
                            res.push_back(i); // 添加结果
                            cnt[s[i]]++; // 将滑动窗口底部元素弹出
                            cursor--;
                            break;
                        }
                    }
                    else{ // 滑动窗口内已有足够多的该元素
                        int k = i;
                        for(; s[k] != s[j]; k++){ // 将该元素及该元素以前的元素一起弹出滑动窗口
                            cnt[s[k]]++;
                            cursor--;
                        }
                        i = k;
                        break;
                    }
                }
                else{ // s[j]未出现在p内
                    for(int k = i; k < j; k++){ // 将j之前的元素弹出
                        cnt[s[k]]++;
                    }
                    i = j;
                    cursor = 0;
                    break;
                }
            }
        }
        return res;
    }
};

标签:子串,窗口,异位,字母,力扣,438,字符串,滑动,leetcode
From: https://www.cnblogs.com/greatestchen/p/16948222.html

相关文章

  • LeetCode刷题笔记
    前言:我是从大四上学期开始刷算法题的,那时候比较迷茫,不知道做什么。想着提升一下自己,就看着B站代码随想录的视频,然后开始在力扣上刷题。当你陷入迷茫,不知道学什么的时候,只要......
  • 力扣 leetcode 11. 盛最多水的容器
    问题描述给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i,0)和(i,height[i])。找出其中的两条线,使得它们与x轴共同构成的容器可以容......
  • 「遍历」字符串中第二大的数字(力扣第1796题)
    本题为12月3日力扣每日一题题目来源:力扣第1796题题目tag:遍历题面题目描述给你一个混合字符串s,请你返回s中第二大的数字,如果不存在第二大的数字,请你返回-1。混合......
  • leetcode.cn 10.正则表达式匹配 记忆化搜索
    心血来潮想刷刷题玩,想起leetcode,注册登录,知道leetcode上的题都比较简单,就勾选难度为“困难”,然后看到此题。读完题,心想这标为“困难”,该不会是得用DFA甚至NFA吧?又仔细看......
  • 力扣09 判断一个数是否是回文数
    力扣09判断一个数是否是回文数题目:给你一个整数x,如果x是一个回文整数,返回true;否则,返回false。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如......
  • 力扣 leetcode 986. 区间列表的交集
    问题描述给定两个由一些闭区间组成的列表,firstList和secondList,其中firstList[i]=[starti,endi]而secondList[j]=[startj,endj]。每个区间列表都是成对不......
  • 力扣 leetcode 1769. 移动所有球到每个盒子所需的最小操作数
    问题描述有n个盒子。给你一个长度为n的二进制字符串boxes,其中boxes[i]的值为'0'表示第i个盒子是空的,而boxes[i]的值为'1'表示盒子里有一个小球。在......
  • #yyds干货盘点# LeetCode程序员面试金典:字符串压缩
    题目:字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串......
  • 反转链表-LeetCode206 改变指向
    LeetCode链接:https://leetcode.cn/problems/reverse-linked-list/题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。示例1:    输入:head=[1,2,......
  • 力扣03 返回最大不重复子串的长度
    力扣03返回最大不重复子串的长度题目:给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。示例1:输入:s="abcabcbb"输出:3解释:因为无重复字符......