字符串-最长不含重复字符的子字符串(mid)

一、题目描述

二、解题思路

本题最小白的思路就是用双指针,取出子串后对子串判断是否含有重复的字符,如果没有重复字符则更新满足条件的最大子串长度。

但是这样做的话时间复杂度非常高,达到了O(n³),超出了题目的最长执行时间。所以要对双指针移动的这一过程进行优化,尽量排除掉肯定不满足条件(含有相同字符)的子串。

这里左右指针移动过程中,右指针的每次移动并不需要让左指针从头再开始遍历。

举个例子:

字符串:        a  b  c  a  c  c  d  b 

下标:            0 1   2  3  4  5  6  7

这里使用nowsubstr = substring(left,right),是个左闭右开区间,nowstr是当前子串

需要检查当前子串是否包含chatAt(right),如果不包含,则说明可以把right++,扩大子串规模

right= 0         left= 0        子串 ""       子串和charAt(right)对比没有重复字符         right++

right= 1         left= 0        子串 a        子串和charAt(right)对比没有重复字符         right++

right= 2         left= 0        子串 ab       子串和charAt(right)对比没有重复字符        right++

right= 3         left= 0        子串 abc      子串和charAt(right)对比有重复字符 a        则代表如果以charAt(right)为最右侧字符时,需要更新left,直到新的substring(left,right)中没有chatAt(right)。这里可以看到left=1就满足了要求,新的子串为 bc。                                然后      right++

right= 4         left= 1        子串 bca       子串和charAt(right)对比有重复字符 c         则代表如果以charAt(right)为最右侧字符时,需要更新left,直到新的substring(left,right)中没有chatAt(right)。这里可以看到left=3就满足了要求,新的子串为 a。                                然后      right++

...

上述过程我们可以看到,因为在之前的比较中,substring(left,right)已经是以right-1位置字符作为最右侧的满足题目条件的子串(不重复字符),我们的left不需要从0再开始分析字符是否重复了【这一点是和题目要求紧密相关的】。

三、代码实现

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param s string字符串 
     * @return int整型
     */
    public int lengthOfLongestSubstring (String s) {
        int maxLength=0;
        int left=0,right=0;
        System.out.println(s.length());
        for(;right<s.length();right++){
            for(;left<=right;left++){
                String substr=s.substring(left,right);
                if(!substr.contains(s.charAt(right)+"")){
                    //left到right没有重复字符
                    break;
                }
            }
            int diff=right+1-left;
            maxLength=maxLength>diff?maxLength:diff;
        }
        return maxLength;
    }
}

四、刷题链接

最长不含重复字符的子字符串_牛客题霸_牛客网

简单路径(c++题解,代码禁止有注释) 内存限制: 512 Mb时间限制: 1000 ms 题目描述 给定一棵 n n 个点的树,每条边上有一个字符。定义 S ( x , y ) S(x,y) 为 x x 到 y y 的简单路径上所有字符按顺序组成的字符串。 给定一个长为 m m 的 T T,求对于树上任意两个点 1 ≤ x , y ≤ n 1≤x,y≤n, LCS ⁡ ( S ( x , y ) , T ) LCS(S(x,y),T)最长长度。 其中, LCS ⁡ ( P , Q ) LCS(P,Q) 表示两个字符串最长公共后缀。例如 LCS ⁡ ( abcde , ccde ) 3 LCS(abcde,ccde)=3。 输入格式 第一行一个整数 T T,表示数据组数。 接下来 T T 组数据,对于每组数据: 第一行两个整数 n , m n,m。 接下来 n − 1 n−1 行,每行两个整数 u , v u,v 以及一个小写字母 c c,表示一条连接结点 u , v u,v 的边,边上的字符为 c c。 最后一行一个长度为 m m 的字符串 T T。 输出格式 共 T T 行,每行一个整数表示答案。 数据范围 对于 30 % 30% 的数据,对于所有的 2 ≤ i ≤ n − 1 2≤i≤n−1,节点 i i 仅与节点 i − 1 i−1 和 i + 1 i+1 相连; 对于 60 % 60% 的数据,对于所有的 2 ≤ i ≤ n 2≤i≤n,节点 i i 仅与至多两个节点相连; 对于 100 % 100% 的数据, 1 ≤ T ≤ 500 1≤T≤500, 2 ≤ n , ∑ n ≤ 1 0 4 2≤n,∑n≤10 4 , 1 ≤ m ≤ 1 0 3 1≤m≤10 3 ,字符串 S S 中仅包含小写英文字母。 样例数据 输入: 3 5 4 1 2 a 2 3 c 2 4 d 1 5 b cfgd 6 4 1 2 a 2 3 c 2 4 d 1 5 b 3 6 d abcd 3 1 1 3 a 2 3 a b 输出: 2 3 0
最新发布
12-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值