最长不重复子串的有趣解法

简介: 最长不重复子串的有趣解法

最长不重复子串是leetcode一道经典的题目,要求找出一个字符串中最长不重复子串的长度

首先清楚一个概念,子串是连续的字符组成的,子序列是不连续的字符组成的。


)常规做法


一种常规的想法就是以每个字符作为起始点,查找以这个字符开始的最长子串,然后输出最大的长度,这种做法需要两层循环,第一层循环是起始字符 s[i],第二层循环是以第一层起始字符后的第一个字符开始 s[j],如果 s[j] 出现在子串 s[i, j] 中,则以 s[i] 开头的最长不重复子串长度就是 j - i。这种做法比较耗时,因为涉及了大量的重复比较。


滑动窗口法


有一种巧妙的方法就是滑动窗口,一般也称为双指针方法,两个指针分别表示窗口的两边。

滑动窗口法的思想是一层循环,每次循环找到以这个字符为结尾的子串,具体做法就是:

  • 外层循环遍历所有字符,初始化窗口两边都为 0,建立一个 hashmap 用于记录当前窗口字符出现次数。
  • 如果当前字符在 hashmap 中已经出现,说明窗口中包含了这个字符,因此将窗口左边逐一向右,并依次减少其 hashmap 出现的次数(因为已经不在窗口中了),直到所有字符出现次数都为 1,说明没有重复了。
  • 这里有一个技巧,就是窗口右边字符出现次数不为 1 的时候我们开始移动左边窗口,这个时候,窗口内只有一个重复元素,就是右边窗口所在的字符,我们需要将左边窗口移动到重复元素之后的第一个字符上,这样左边窗口到右边窗口的子串就不会有重复元素了。
  • 这个地方其实也有一次小循环,但是相比第一种方法,减少了重复比较的次数。
  • 如果当前字符没有出现过,则以当前右边窗口所在字符为结尾的不重复子串就是窗口的长度。判断当前长度和已有记录长度,选择最大长度,右边窗口继续右移,考察下一个字符。
  • 这个地方也有一个技巧,就是当前字符的左边窗口边界一定是前一字符左边窗口边界及其之后,因为前一字符的左边窗口是其重复字符后的第一个字符,而当前字符包含了前一字符,因为其左边界不可能位于前一字符左边界的前面。

代码如下:


#include <algorithm>
#include <string>
#include <unordered_map>
using namespace std;
class Solution
{
public:
    int lengthOfLongestSubstring(string s)
    {
        int n = s.size();
        if (n == 0)
            return 0;
        unordered_map<char, int> m;
        int left = 0, len = 0;
        for (int i = 0; i < n; i++)
        {
            m[s[i]]++;
            while (m[s[i]] > 1)
            {
                m[s[left++]]--;
            }
            len = max(len, i - left + 1);
        }
        return len;
    }
};


总结


在解这道题的时候我想到的是,其实很多时候都需要拥有这种以该字符作为结尾这种逆向思维的方式,往往能找到比较有效的方法。

目录
相关文章
|
Java 数据库连接 数据库
使用原生JDBC动态解析并获取表格列名和数据
使用原生JDBC动态解析并获取表格列名和数据
173 0
|
存储 Android开发
解决了一个大家都有可能遇到的奇葩权限问题
解决了一个大家都有可能遇到的奇葩权限问题
解决了一个大家都有可能遇到的奇葩权限问题
|
8月前
|
监控 前端开发 Java
构建高效Java后端与前端交互的定时任务调度系统
通过以上步骤,我们构建了一个高效的Java后端与前端交互的定时任务调度系统。该系统使用Spring Boot作为后端框架,Quartz作为任务调度器,并通过前端界面实现用户交互。此系统可以应用于各种需要定时任务调度的业务场景,如数据同步、报告生成和系统监控等。
293 9
|
Ubuntu Linux Windows
wsl常用命令大全
WSL(Windows Subsystem for Linux)的常用命令,包括查看帮助、更新WSL、查看和管理Linux发行版、设置默认版本等,以帮助用户更有效地管理和使用WSL环境。
707 1
|
Oracle 关系型数据库 Linux
服务器Centos7 静默安装Oracle Database 12.2
服务器Centos7 静默安装Oracle Database 12.2
552 0
|
数据可视化 物联网
Threejs物联网,养殖场3D可视化(三)模型展示,轨道控制器设置,模型沿着路线运动,模型添加边框,自定义样式显示标签,点击模型获取信息
Threejs物联网,养殖场3D可视化(三)模型展示,轨道控制器设置,模型沿着路线运动,模型添加边框,自定义样式显示标签,点击模型获取信息
1215 15
Threejs物联网,养殖场3D可视化(三)模型展示,轨道控制器设置,模型沿着路线运动,模型添加边框,自定义样式显示标签,点击模型获取信息
|
索引
foreach、for in和for of之间区别?
foreach、for in和for of之间区别?
573 0
|
消息中间件 人工智能 Serverless
函数计算FC降价全解析,最高幅度达93%,怎么用才便宜?
今年云栖大会,函数计算3.0全新升级,相对函数计算2.0,3.0版本突出易用性、高弹性,并且可以和更多阿里云服务无缝集成。业内首发神龙 Serverless GPU 架构,冷启动大幅优化,全链路调度延时降低 80%,函数执行性能波动率降低 70%;作为事件驱动的全托管计算服务,足够轻量灵活,让用户以更少的代码,更好、更快地实现业务创新。函数计算 FC 通过大规模的资源池化和调度策略优化实现降本,阶梯定价最高降幅可达 93%。
函数计算FC降价全解析,最高幅度达93%,怎么用才便宜?
|
网络协议 文件存储
如何公网远程连接本地群晖NAS中的WebDAV
如何公网远程连接本地群晖NAS中的WebDAV
1165 0