leetcode_3

@YangYang48

找最长子串的长度

问题描述

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

示例 1:

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

示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

思路1:滑动窗口

这里以c/c++语言来具体化

  1. 找到一个字符串str[],可以用来存放所有可能

输入:abcabcbb
a,ab,abc,bca,cab,bc,b

  1. 用string类对字符串进行操作

    • operator+ 字符串连接
    • getline 从输入流读入一行
    • substr 得到字符串
    • find 查找
    • begin 字符串的开头
    • end 字符串的结尾

其他string类的操作,点击这里即可;

具体思路开始(可以参考下面几幅图)

  1. 在0,s.length区间循环
    去除子字符串的重复字符
    找位置,设置cursor游标
  2. 去除字符,提取子串substr(sursor+1)
    增加子字符串的重复字符
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

代码

/*滑动窗口*/
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len = 0;    //最大长度
        //int start = 0;    //找上次重复字符的右边位置
        int cursor = 0;    //游标
        int i=0;
        string str = ""; //子字符串
        for(i=0; i<s.length(); i++){
            if(str.find(s[i]) == -1){    //是否重复字符
                str = str + s[i];
                len=str.length();
            }
            else{    //找到重复子串
                if(len<str.length())
				{
				   len = len>str.length() ? len : str.length();    //更改最大字串长度
                   //start = s.find_first_of(s[i], start) + 1;
				}
                cursor = str.find_first_of(s[i]);   //在子串中查找重复位置
                str = str.substr(cursor+1) + s[i];    //从重复字符处后一位置截取字符串
            }
        }
        len = len>str.length() ? len : str.length();
        //cout<<s.substr(start,len); //用于输出第一次出现的最大子串
        return len;
    }
};

修改之后,添加start来记录最大子串第一次出现的右边位置(删除三行//即可)
调用substr可以输出第一次出现的最大子串

思路2:哈希表

理解了上面的思路1之后,思路2就很好理解了
思路2主要使用了哈希表存放每一个元素的上一次重复的右边位置(可结合下图)

  1. max与i-left+1作比较(注:这里的max为上面的len,这里的left为上面的游标,这里的hash[s[i]]为上面的start,可以理解哈希表为start数组)
  2. left移动,并重新计算left与上一个重复数的右边位置
  3. left不移动的情况只有两种
  • s[i]重复,且left>=hash[s[i]],游标不小于第i个位置下一个位置
  • s[i]不重复hash[s[i]]=0

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

/*哈希表*/
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
    //设置字符数组
    int hash[256]={0};//hash[s[i]]是s[i]上一次出现的位置+1
    int i,left=0,max=0;
    for(i=0;i<s.length();i++)
    {
        if(hash[s[i]]==0||hash[s[i]]<left)//判断left是否要移动
        {
            max=max>(i-left+1)?max:(i-left+1);//left不移动
        }
        else
        {
            left=hash[s[i]];
        }
        hash[s[i]]=i+1;//hash[s[i]]为是s[i]前一次出现的位置+1
    }
    return max;
}
};

这里的hash[s[i]]中的s[i]为字符的ASCII码值,这就可以理解为什么hash数组是256
当然也可以改成hash[s[i]-‘0’]这种形式,原理是一样的,笔者在devc++上都测试可用
如果本文对宝宝打开思路有帮助,可以点个赞哦~

参考

[1]陈乐乐
[2]力扣官方

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值