[Leetcode] 567. Permutation in String 解题报告

本文介绍了一种用于判断一个字符串是否包含另一个字符串的所有排列的方法。通过两种实现方式——使用字母表和哈希表来检查s2是否包含s1的所有排列。提供了详细的思路解析及C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. In other words, one of the first string's permutations is the substring of the second string.

Example 1:

Input:s1 = "ab" s2 = "eidbaooo"
Output:True
Explanation: s2 contains one permutation of s1 ("ba").

Example 2:

Input:s1= "ab" s2 = "eidboaoo"
Output: False

Note:

  1. The input strings only contain lower case letters.
  2. The length of both given strings is in range [1, 10,000].

思路

1、字母表:定义一个长度为26的数组,用来存储s1和s2中长度为s1.length()的子串的字符出现次数差。然后定义窗口[0, l1],让它的右边界在[l1, l2)之间滑动,同时更新数组。一旦发现更新后的数组为全零,则返回true。

2、哈希表:其实思路和字母表一样,但是更精妙一些:就是一旦碰到一个不存在于s1中的字符,假设在i处,则让start今后从i+1或者之后再开始,而不需要像字母表中那样顺序渐进的更新start。然而由于代码控制分支过多,运行时间反而不如字母表法。

代码

1、字母表:

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        int l1 = s1.length(), l2 = s2.length();
        if (l1 > l2) {
            return false;
        }
        vector<int> count(26, 0);
        for (int i = 0; i < l1; ++i) {
            ++count[s1[i] - 'a'];
            --count[s2[i] - 'a'];
        }
        if (allZero(count)) {
            return true;
        }
        for (int i = l1; i < l2; ++i) {
            --count[s2[i] - 'a'];
            ++count[s2[i - l1] - 'a'];
            if (allZero(count)) {
                return true;
            }
        }
        return false;
    }
private:
    bool allZero(vector<int> &count) {
        for (int i = 0; i < count.size(); ++i) {
            if (count[i] != 0) {
                return false;
            }
        }
        return true;
    }
};

2、哈希表:

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        unordered_map<char, int> hash;  // map from char to its appear count
        for (auto c : s1) {
            ++hash[c];
        }
        int start = -1;
        for (int i = 0; i < s2.length(); ++i) {
            if (hash.count(s2[i]) > 0) {    // s2[i] exist in s1
                if (hash[s2[i]] > 0) {      // append s2[i] directly
                    --hash[s2[i]];
                    if (start == -1) {
                        start = i;
                    }
                    if (i - start + 1 == s1.length()) {
                        return true;
                    }
                }
                else {                      // increase start until s2[start] == s2[i]
                    while(hash[s2[i]] == 0) {
                        ++hash[s2[start++]];
                    }
                    --hash[s2[i]];
                    start = min(start, i);
                }
            }
            else {                          // s2[i] does not exist in s1
                if (start != -1) {          // recover hash[s2[start]] until start == i
                    while (start < i) {
                        ++hash[s2[start]];
                        ++start;
                    }
                    start = -1;
                }
            }
        }
        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值