无重复字符的最大子串

原题描述

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

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

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

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

示例 4:
输入: s = “”
输出: 0

提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

一题多解

解法一(最原始的暴力)

思路:
首先想到就是双指针法,一个指针指向子串的头,一个指向子串的尾。
1、开始时头指针h 指向字符串的首字符,尾指针 t指向字符串的第二个字符。还需要借助一个指针p用来访问子串内的元素。
2、固定一个子串后,需要用p遍历子串的每一个元素并与子串的最后一个字符做比较,以确定子串是否是不重复的子串。
3、子串内无重复的字符,则当前以头指针位置为起点的无重复子串长度加1(但不确定其他起点的无重复子串的最大长度是多少,需要打擂确定),尾指针加1,指针p重置回到头指针的位置,重复步骤2;子串内有重复的字符,则尾指针不动,头指针加1,指针p重置回到头指针位置。重复步骤2和3,直到尾指针来到字符串的末尾。
初始状态

解法二(好一点的优化)

思路:

优化解法一的步骤三:当子串发现重复元素的时候,头指针是不是不需要一个位置一个位置地向前移动呢?KMP算法给了我启发,在重复的子串中,从头指针到重复元素所在的位置(也就是指针p指向的位置),这一段字符串中的任一子序列,均不可能与当前子串的最后一个字符构成一个不重复的子串,因为这些子串必定包含了两个重复的字符(指针p指向的元素和尾指针指向的元素)。因此,当子串发现重复元素的时候,我们不需要把头指针一次一次向前加1,而是可以直接把头指针移到指针p指向的元素的后面一个元素。这样就可以减少头指针移动的次数,从而降低时间复杂度。

代码:

class Solution {
    public int lengthOfLongestSubstring(String s) {
        
        if(s.equals(""))//空串直接返回长度为0
            return 0;

        int h=0;//h->子串头
        int t=h+1;//t->子串尾
        int p=0;//p->当前子串中待检查元素的位置
        int max=1;
        char temp='0';
        while(t<s.length()){
                /*遍历当前子串,看有没有与子串中最后一个字符重复的 */
                temp=s.charAt(t);
                while(p<t &&s.charAt(p)!=temp){
                    p++;
                }

                /*有重复 */
                if(p<t){
                    h=p+1;//把子串左端滑到重复的位置后面
                }
                /**没重复 */
                else{
                    if(t-h+1>max)//打擂维护最大子串长度
                    	max=t-h+1;
                }
                p=h;    
                t++;
        }

        return max;
    }
}

优化后速度就挺快了

解法三(看题解后我认为比较好的方法)

思路:
数据结构:滑动窗口–双指针的形象化思考(便于代码模板化)
定义:一个自定义的满足某个性质的队列(本题滑动窗口是一个只包含无重复字符的字符串的队列)
基本操作:1、入队 2、出队
怎么维护
1、入队(队尾指针加1)
2、判断队列前面元素是否要出队(通过判断当前队尾是否与队列其他元素相同(可以遍历队列,也可以借助哈希集合,如java中的HashMap) )
3、判断成立,则n个元素出队(队头指针加n)
在遍历一个字符串的过程始终维护这样一个滑动窗口(重复1、2和3步骤)

滑动窗口
代码:

在这里插入代码片
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值