c++算法与数据结构的养成之路

本文对比了力扣题号3——无重复字符的最长子串问题中的暴力求解和滑动窗口算法。暴力法因时间复杂度过高导致超时,而滑动窗口法巧妙利用双指针优化,降低了时间复杂度。讲解了两种方法的思路、代码实现及其优化技巧。

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

滑动窗口法和暴力求解法的battle

力扣题号以及题目描述:

力扣题号

题号:3
题名:无重复字符的最长子串
难度:中等

题目表述

在这里插入图片描述

暴力求解的思路:

用i遍历s,再从s[i]开始,用j遍历剩余的字符串,将字符储存到哈希表里,当哈希表里出现重复的字符时跳出内层循环,根据hash表的size函数,得到哈希表的长度,保存此长度。当外层循环结束时,得到最大的长度值。

bug:

在力扣求解时,会超时,算法的时间复杂度O(N^2)。

代码如下:
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
       int length =  s.size();
       vector<int> result(length,-1);
       //unordered_map<int,char>  table_hash;
       unordered_map<char,int>  table_hash;
       for(int i = 0; i != s.size(); ++i){
           for(int j = i; j != s.size(); ++j){
               if(table_hash.find(s[j]) != table_hash.end()) break;
               else table_hash[s[j]] = s[j] - '0';
           }
           result[i] = table_hash.size();
           table_hash.clear();
       }
       return  *max_element(result.begin(),result.end());
    }
};
结果

在这里插入图片描述

滑动窗口法的思路

利用双指针的思想,第一个指针,在窗口的左边界,另一个指针,在窗口的右边界。首先移动右边界,判断是否满足不重复的条件,若是不满足,则移动窗口的左边界。在移动左边界之前需要计算两个指针的距离,这个值在求解过程中的最大值就是所需的答案。

注意事项

滑动窗口法的形式,是类似以下这种形式:

for(int i = 0 ; i < length; ++i){
	while(xxxxx){
	++j;
	}
}

经过测试吧,i这个指针是滑动窗口的右边界比较好,因为一定会滑到头。
j这个指针,则为滑动窗口的左边界。

hashmap的理解

之前我使用 unordered_map<char,int>这个容器时,总喜欢将字符char 作为key,然后呢 将 char字符 - ‘0’ 字符 作为数字 存储到 value 里面。
实际上 对 value 这个值应用不够充分。可以将 value 存储成 字符出现的次数。
还有一个特殊的点是,hashmap里面没有存储的字符,当我们利用hashmap使用该字符时,它的value值默认是0。

代码如下:
class Solution {
public:
    unordered_map<char,int> hash_table;
    int lengthOfLongestSubstring(string s) {
        int len  = s.size();
        int i,j=0;// 两个指针
        int length = 0;
        for(j = 0; j != len; ++j){
            while(hash_table[s[j]] != 0){   //s[j] 出现过
                --hash_table[s[i]];
                ++i;
                
            }            
            length = max(length,j - i + 1);
            ++hash_table[s[j]];
        }
        return length;
    }
};
运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值