哈希表数组

滑动窗口法

一、题源:

242. 有效的字母异位词
问题描述

给定两个字符串 st ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 st 中每个字符出现的次数都相同,则称 st 互为字母异位词。

二、 思路:

1、映射

unordered_map 可以很方便的实现出现的字母及出现次数的计算。

参考代码如下


class Solution {
public:
    bool isAnagram(string s, string t) {
        unordered_map<char,int> map;
        for(auto it = s.begin(); it != s.end(); it++) ++map[*it] ;
        for(auto it = t.begin(); it != t.end(); it++) --map[*it] ;
        for(auto it = map.begin(); it != map.end(); it++) if(it ->second != 0) return false ;
        return true;
    }
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)

2、数组

数组实际上是最简单的哈希表,数组的大小就是散列表的大小,将关键字映射到数组下标的函数就是散列函数。

使用数组的好处是:

  • 消耗内存空间较小
  • 散列函数的计算量较小。

使用数组一般是针对数值大小有限且机制的情况。

参考代码如下


class Solution {
public:
    bool isAnagram(string s, string t) {
        int letters[26];
        memset(letters, 0, sizeof(letters));
        for(auto it = s.begin(); it != s.end(); ++it) ++letters[*it - 'a'];
        for(auto it = t.begin(); it != t.end(); ++it) --letters[*it - 'a'];
        for(size_t i =0; i < 26; ++i) if(letters[i]) return false;
        return true;
    }
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)

三、相关题目及C++实现

383. 赎金信

问题描述:

给你两个字符串:ransomNotemagazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false

magazine 中的每个字符只能在 ransomNote 中使用一次。

实现:


class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        int letters[26] = {0};
        for(auto it = magazine.begin(); it != magazine.end(); ++it) ++letters[*it - 'a'];
        for(auto it = ransomNote.begin(); it != ransomNote.end(); ++it) --letters[*it - 'a'];
        for(auto i = 0; i < 26; i++) if(letters[i] < 0) return false;
        return true;
    }
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)

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

问题描述:

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

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

实现:


class Solution {
public:
    bool isEqual(int* letters)
    {
        for(auto i = 0;i < 26; i++) if(letters[i]) return false;
        return true;
    }
    vector<int> findAnagrams(string s, string p) {
        vector<int> result;
        int letters[26] = {0}; 
        auto headIt = s.begin(), rearIt = s.begin();
        if(s.size() < p.size()) return result;
        for(auto it = p.begin(); it != p.end(); ++it) ++letters[*it - 'a'];
        for(; rearIt - s.begin() < p.size(); ++rearIt) --letters[*rearIt - 'a'];
        for(;rearIt < s.end(); ++rearIt, ++headIt)
        {
            if(isEqual(letters)) result.push_back(headIt - s.begin());
            --letters[*rearIt - 'a'];
            ++letters[*headIt - 'a'];
        }
        if(isEqual(letters)) result.push_back(headIt - s.begin());
        return result;
    }
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)

做了一点优化,通过 nonZeroNum 来记录 letters数组 中的非零元素个数。


class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> result;
        int letters[26] = {0}; 
        int nonZeroNum = 0;
        auto headIt = s.begin(), rearIt = s.begin();
        if(s.size() < p.size()) return result;
        for(auto it = p.begin(); it != p.end(); ++it) ++letters[*it - 'a'];
        for(; rearIt - s.begin() < p.size(); ++rearIt) --letters[*rearIt - 'a'];
        for(auto i = 0; i < 26; ++i)if(letters[i]) ++nonZeroNum;
        for(;rearIt < s.end(); ++rearIt, ++headIt)
        {
            if(!nonZeroNum) result.push_back(headIt - s.begin());
            if(letters[*headIt - 'a'] == -1) --nonZeroNum;
            else if(letters[*headIt - 'a'] == 0) ++nonZeroNum;
            ++letters[*headIt - 'a'];
            if(letters[*rearIt - 'a'] == 1) --nonZeroNum;
            else if(letters[*rearIt - 'a'] == 0) ++nonZeroNum;
            --letters[*rearIt - 'a'];
        }
        if(!nonZeroNum) result.push_back(headIt - s.begin());
        return result;
    }
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值