cstring判断是否包含子串_最长子串-滑动窗口

接下来我会找出LeetCode中一些比较有代表性的题,带来它的算法和讲解

很多题目,使用一般的暴力算法很多都能解出来,但时间复杂度可能是 O(n3),会比最优解慢很多,尤其是数据量变大时。

在我们实际项目中编写代码时会遇到各种情况,组织数据,处理数据,如果能在特定的情况使用特定的算法,就可以发挥事半功倍的效果,很有现实意义。

原题链接

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 :
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

暴力

这是一个比较经典的问题,查找无重复最长子串。

先看我最开始给出的解法

思路比较简单,借助Set,我可以很快的判断一个字符是否在一个集合里

从第一个字符开始开始遍历每个字符,然后从这个字符开始到最后一个字符,依次加入Set

如果Set没有就加入,一旦出现重复判断之前的最长长度和当前的最长长度,取较大值,Set清空

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Set<Integer> t = new HashSet<>();
        int max = 0;
        for (int i = 0; i < s.length(); i++) {
            for (int j = i; j < s.length(); j++) {
                int a = s.charAt(j);
                if (!t.contains(a)) {
                    t.add(a);
                } else {
                    max = t.size() > max ? t.size() : max;
                    t.clear();
                    break;
                }
            }
        }
        if(t.size() > max){
            max = t.size();
        }
        return max;
    }
}

滑动窗口

先看解法

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int max = 0;
        Set<Character> t = new HashSet<>();
        for (int i = 0, j = 0; i < s.length(); ) {
            if (j >= s.length()) {
                break;
            }
            if (!t.contains(s.charAt(j))) {
                t.add(s.charAt(j));
                max = Math.max(max, j - i +1);
                j++;
            }else{
                t.remove(s.charAt(i++));
            }
        }
        return max;
    }
}

暴力法有个明显的问题,比如我判断 abcabcbb

在第一字符时判断

a
ab
abc
abca

在第二个字符时判断

b
bc
bca

会有大量重复且不必要的判断

那么怎么避免呢

当我判断第一个字符到 abca 时,不在完全退回第二个字符重新判断,而是保留右侧的配置,左侧右移一位,那么现在就成了不重复时右侧游标右移,存在重复字符时,左侧游标右移,同时记录中间的最长长度

左侧游标和右侧游标依次滑动右移,就仿佛是一个会移动的窗口,中间的某个最大长度即为不含有重复字符的最长子串

滑动窗口优化

当我们遇到一个字符串pasdsad,使用上述算法

p
pa
pas
pasd
asd
sd
d
ds

因为下一个字符是s,所以左侧游标移动了3次才移除了当前窗口内s

但是如果直接能跳到s位置呢

那么又会减少很多次操作

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length(), ans = 0;
        Map<Character, Integer> map = new HashMap<>();
        for (int j = 0, i = 0; j < n; j++) {
            if (map.containsKey(s.charAt(j))) {
                i = Math.max(map.get(s.charAt(j)), i);
            }
            ans = Math.max(ans, j - i + 1);
            map.put(s.charAt(j), j + 1);
        }
        return ans;
    }
}

通过Map映射记录上一个重复字符的位置,发生重复是可使左侧游标直接跳到之前的重复位置。

关注我的Github项目,开启Java进阶之路,欢迎star

Asens/Java-Advance​github.com
c662cdf449ab2f747924d1680bae36ab.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给下面代码每一行给上注释并说明这段代码的意思#include "pch.h" #include "FinBudgetSupport.h" #include <map> time_t StringToDateTime(char* str) { tm tm_; int year, month, day, hour, min, sec; afxDump << str << "\n\n\n\n"; sscanf_s(str, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &min, &sec); tm_.tm_year = year - 1900; tm_.tm_mon = month - 1; tm_.tm_mday = day; tm_.tm_hour = hour; tm_.tm_min = min; tm_.tm_sec = sec; tm_.tm_isdst = -1; time_t t_ = mktime(&tm_); return t_; } CString DateTimeToString(time_t _time) { tm *_tm = new tm(); gmtime_s(_tm ,&_time); CString t_str; t_str.Format(_T("%d-%d-%d %d:%d:%d"), _tm->tm_year+1900, 1+_tm->tm_mon, _tm->tm_mday, _tm->tm_hour , _tm->tm_min, _tm->tm_sec); delete _tm; return t_str; } CString _toCString(double _value) { CString t_str; t_str.Format(_T("%lf"), _value); return t_str; } CString _toCString(int _value) { CString t_str; t_str.Format(_T("%d"), _value); return t_str; } double _toDouble(CString _str) { return _ttof(_str); } char* CStringToCharArray(CString str) { int str_len = WideCharToMultiByte(CP_ACP, 0, str, str.GetLength(), NULL, 0, NULL, NULL);//计算字节数 char* CharArray = new char[str_len + 1]; WideCharToMultiByte(CP_ACP, 0, str, str.GetLength(), CharArray, str_len, NULL, NULL); CharArray[str_len] = '\0'; return CharArray; } void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c) { std::string::size_type pos1, pos2; pos2 = s.find(c); pos1 = 0; while (std::string::npos != pos2) { v.push_back(s.substr(pos1, pos2 - pos1)); pos1 = pos2 + c.size(); pos2 = s.find(c, pos1); } if (pos1 != s.length()) v.push_back(s.substr(pos1)); }
最新发布
06-10

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值