(力扣)LeetCode567. 字符串的排列(C语言)

一、环境说明

  1. 本文是 leetcode 567题 : 字符串的排列,使用c语言实现
  2. 使用哈希思想+滑动窗口+双指针实现。
  3. 测试环境:Visual Studio 2019

二、代码展示

bool checkInclusion(char * s1, char * s2){
    int n=strlen(s1),m=strlen(s2);
    if(n>m){//s1比s2长
        return false;
    }
    int hash[26]={0};
    for(int i =0;i<n;i++){
        hash[s1[i]-'a']++;//字符在hash表加1
    }
    int left = 0,right = 0;
    for(right = 0;right<m;right++){
        hash[s2[right]-'a']--;//右指针字符在hash表减1
        while(hash[s2[right]-'a']<0){//s1中没有对应字符了
            hash[s2[left]-'a']++;//左指针字符在hash表加1
            left++;//左指针右移
        }
        if(n==right-left+1){//当滑动窗口大小等于n
            return true;
        }
    }
    return false;
}

三、思路分析

  1. 先分析题目,s1的排列,就是字符顺序打乱重组的s1,s1的排列和s1本身长度不变,元素不变。字符串匹配,很容易想到滑动窗口;元素不变,很容易想到哈希思想,又是26个字母,直接用数组哈希。这题我们就用一下滑动窗口和数组哈希。
  2. 首先我们建立哈希数组,数组大小对应26个字母。遍历s1,在哈希数组里记录每一个元素个数。意为可以在s2中使用的元素个数。
  3. 然后遍历s2,采用双指针,left和right,使得滑动窗口大小可变。要在s2中找s1的排列,最终找到的滑动窗口长度一定是s1的长度n。每次循环,right右移,同时right指向元素的个数,hash[s2[right]-‘a’]减1。
  4. 当right指向新的元素,而哈希数组中对应的元素不足,这时就需要将left不断右移,每次移动left[s2[left]-‘a’]加1,直到重新满足哈希表中所有元素都大于0,意味着s1的元素现在够用了,可以继续匹配s2了。
  5. 重复3、4的过程,直到滑动窗口大小等于n时,此时刚好所有s1中元素都被用来匹配了s2中的一个子串,也就是s1的排列,是s2的一个子串。

四、AC

AC

五、复杂度分析

  1. 时间复杂度:O(n+m) ,n是s1长度,m是s2长度,O(n)是遍历s1的时间复杂度。O(m)是遍历s2的时间复杂度,由于遍历s2存在左指针右移的情况,实际上,最坏时间复杂度是O(2m),最好情况是O(L),L是数组长度。
  2. 空间复杂度:O(L)L是数组长度。

对双指针不了解的同学,可以先了解双指针的题目 移动零
对哈希思想不了解的同学,可以先了解哈希思想中的数组方法 哈希集合的创建
本题思路参考 力扣官方题解

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清墨韵染

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值