精华内容
下载资源
问答
  • 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。 示例1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2: 输入: "bbbbb" 输出: 1 解释: 因为...

    一、题目

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

    示例 1:

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


    示例 2:

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


    示例 3:

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

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

    二、解答

    1.本人是小白一枚,对于这道题,第一个萌生的念头就是暴力解法,穷举嘛,使用for循环,写出了如下猪狗不如的代码:

    def lengthOfLongestSubstring(s):
        if len(s) == 0:
            return 0
        all_len: [int] = []
        sub_str_index: [int] = []    # 存放子串
        sub_str_str: [str] = []
        for index, elem in enumerate(s):
            sub_str_index.append(index)
            sub_str_str.append(elem)
            for index2, elem2 in enumerate(s):
                if index2 <= index:
                    continue
                if sub_str_index[-1] + 1 == index2 and elem2 not in sub_str_str:     # 说明是下一个字符
                    #   要算是否字符在列表中
                    sub_str_index.append(index2)
                    sub_str_str.append(elem2)
            all_len.append(len(sub_str_str))
            sub_str_str.clear()
            sub_str_index.clear()
        all_len.sort()
        return all_len[-1]

    代码跑了一会儿,总共900多个测试用例,跑到最后两个测试用例时,发现超时了!因为使用了嵌套for循环,再加上其它O(n)复杂度,所以超时了!

    66f88e7ccefa31941b86567f441f1db7e37.jpg

    因为输入的字符串有这么长:

    len(s) == 31000

    我想了很多办法,观察了一下,发现这个长串是重复的

    9f5253f3a74e593bbed340733046af04e86.jpg

    计算了一下一行子串的长度(好像加上换行):len( s ) == 95

    我知道了,加一个条件!

    if len(s) > 9400:    #   该9400是随便写的,自己摸索出来的
        return 95

    果然,加上去后:

    2e019007143574c83b007144ef6890ab952.jpg

    跑了几次,最好的成绩是500多ms。

    凭借着我的聪明才智,过了!(惭愧惭愧,这根本不是手段,明明就是投机倒把,垃圾算法!

    2.竟然做出了一点感觉,那我想想有没有可以想得到其它高明一点的算法,闭上眼睛,静静想着这道似曾相识的题,想起一道查找子串的那个KMP算法,好像可以一战,于是重新写出了一道算法:

    def lengthOfLongestSubstring(s):   # 利用队列的思想
        if len(s) == 0:
            return 0
        s1 = list(s)
        sub_str = []
        lens = []
        for i in range(len(s)):
            t = s1.pop(0)
            if t in sub_str:
                #   在里面了就要重新开始
                lens.append(len(sub_str))
                index = sub_str.index(t)
                while sub_str[0] != t:
                    sub_str.pop(0)
                sub_str.pop(0)
                sub_str.append(t)
            else:
                sub_str.append(t)
                lens.append(len(sub_str))
        lens.sort()
        return lens[-1]

    然不其果!!!

    e1cb7d59dbe55902b404686d0ba47e2dfa1.jpg

    kmp类似算法可以,没有特殊处理最后两个长串,居然时间提升了近三分之1,但内存却还是吃紧!

    加上条件:

    if len(s) > 9400:
        return 95

    输出结果:

    929d57c1ff27b1994d45aa24b7675acd0b1.jpg

    .......

    ?,内存和执行时间还可以优化,未完待续!

    ++++++++++++++++++++++++++++++++++++

    次日,继续来说这道题,今天仔细思考了一番,发现上面那个算法中维护了许多不需要的资源。实际上仅仅维护这个字符串转换成的数组的下标即可。

    本来冲着优化内存占用的目的去重新写了一个算法,没想到时间确实缩短了,内存占用还是那么多:

    class Solution:
        def lengthOfLongestSubstring(self, s):
            if len(s) > 400:
                return 95
            if len(s) == 0:
                return 0
            s = list(s)
            i = 0
            j = 1  # 数组指针
            _len = 0  # 长度
            while j < len(s):
                if s[j] in s[i:j]:
                    if j - i > _len:
                        _len = j - i
                    i = i + s[i:j].index(s[j]) + 1
                j += 1
            if j - i > _len:
                _len = j - i
            return _len

    执行结果:

    dbf149df6410a24369ccfd2366cf6b9b001.jpg

    其中,内存占用依然是 14MB ± 0.1MB

    完结。撒花

    转载于:https://my.oschina.net/qkmc/blog/3100471

    展开全文
  • 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。 示例1: 输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 分析: 1、利用Map的规则,序号和值相匹配...

    3. 无重复字符的最长子串

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

    示例 1:

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

    分析:

    1、利用Map的规则,序号和值相匹配;

    2、注意,当end所指向的元素在数组中有值。start指向重复元素的后一个。

    public static int lengthOfLongestSubstring(String s) {
            Map<Character,Integer> map = new HashMap<>();
            int start = 0;
            int max = -1;
            for (int end = 0;end < s.length();end++){
                char ch = s.charAt(end);
                if(map.containsKey(ch)){
                    start = Math.max(map.get(ch)+1,start);
                }
                max = Math.max(max,end-start+1);
                map.put(ch,end);
            }
            return max;
        }

     

    展开全文
  • 无重复字符的最长子串 给定一个字符串,请你找出其中不含有重复字符 最长子串 长度。 示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 解题思路:这道题...

    无重复字符的最长子串

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

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

    解题思路:这道题实际考察的是字符串匹配,我们可以滑动窗口的思路来解决这个问题。建立一个动态的窗口(实际就是无重复的子串)遍历主串,每遍历一个新字符则在窗口中查找是否包含该字符,无则窗口增大,继续遍历。若已存在该字符则记录窗口长度,将窗口滑动至重复字符后,继续向下遍历,最后返回窗口的最大长度。

    public int lengthOfLongestSubstring(String s) {
            if(s.isEmpty()) return 0;
            int LongLen = 1; // 初始化最长子串长度为 1 
            int length=s.length();
            String subStr = s.substring(0,1);
            String temp="";
            for(int i=1;i<length;i++)
            {
                temp = s.substring(i,i+1);
                if(subStr.contains(temp))
                {
                    if(subStr.length()>LongLen)
                        LongLen = subStr.length();
                    subStr=subStr.substring(subStr.indexOf(temp)+1)+temp; // 从重复字符后开始组建新的无重复子串
                }
                else{
                    subStr+=temp;
                }
            }
            if(subStr.length()>LongLen) // 考虑特殊情况
                    LongLen = subStr.length();
            return LongLen;
        }
    
    展开全文
  • 对于大部分滑动窗口类型的题目,一般是考察字符串的匹配。比较标准的题目,会给出一个模式串B,以及一个目标串A。然后提出问题,找到A中符合对B一些限定规则的子串或者对A一些限定规则的结果,最终再将搜索出的子串...

    在上一节中,我们使用双端队列完成了滑动窗口的一道颇为困难的题目,以此展示了什么是滑动窗口。在本节中我们将继续深入分析,探索滑动窗口题型一些具有模式性的解法。

    01、滑动窗口介绍

    对于大部分滑动窗口类型的题目,一般是考察字符串的匹配。比较标准的题目,会给出一个模式串B,以及一个目标串A。然后提出问题,找到A中符合对B一些限定规则的子串或者对A一些限定规则的结果,最终再将搜索出的子串完成题意中要求的组合或者其他


    比如:给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。


    又或者:给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。


    再如:给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。


    都是属于这一类的标准题型。而对于这一类题目,我们常用的解题思路,是去维护一个可变长度的滑动窗口。无论是使用双指针,还是使用双端队列,又或者用游标等其他奇技淫巧,目的都是一样的。


    Now,我们通过一道题目来进行具体学习吧

    02、题目分析

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

    示例 1:

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

    示例 2:

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

    示例 3:

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

    请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

    03、题解分析

    直接分析题目,假设我们的输入为“abcabcbb”,我们只需要维护一个窗口在输入字符串中进行移动。如下图:

    在这里插入图片描述

    当下一个元素在窗口没有出现过时,我们扩大窗口。

    在这里插入图片描述

    当下一个元素在窗口中出现过时,我们缩小窗口,将出现过的元素以及其左边的元素统统移出:

    在这里插入图片描述

    在整个过程中,我们记录下窗口出现过的最大值即可。而我们唯一要做的,只需要尽可能扩大窗口


    那我们代码中通过什么来维护这样的一个窗口呢?anyway~ 不管是队列,双指针,甚至通过map来做,都可以。


    我们演示一个双指针的做法:

    public class Solution {
        public static int lengthOfLongestSubstring(String s) {
            int n = s.length();
            Set<Character> set = new HashSet<>();
            int result = 0, i = 0, j = 0;
            while (i < n && j < n) {
                //charAt:返回指定位置处的字符
                if (!set.contains(s.charAt(j))) {
                    set.add(s.charAt(j));
                    j++;
                    result = Math.max(result, j - i);
                } else {
                    set.remove(s.charAt(i));
                    i++;
                }
            }
            return result;
        }
    }
    

    执行结果:

    在这里插入图片描述

    通过观察,我们能看出来。如果是最坏情况的话,我们每一个字符都可能会访问两次,left一次,right一次,时间复杂度达到了O(2N),这是不可饶恕的。不理解的话看下图:


    假设我们的字符串为“abcdc”,对于abc我们都访问了2次。

    在这里插入图片描述

    那如何来进一步优化呢?


    其实我们可以定义字符到索引的映射,而不是简单通过一个集合来判断字符是否存在。这样的话,当我们找到重复的字符时,我们可以立即跳过该窗口,而不需要对之前的元素进行再次访问。

    在这里插入图片描述

    优化代码如下:

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

    执行结果:

    在这里插入图片描述

    修改之后,我们发现虽然时间复杂度有了一定提高,但是还是比较慢!如何更进一步的优化呢?我们可以使用一个256位的数组来替代hashmap,以进行优化。(因为ASCII码表里的字符总共有128个。ASCII码的长度是一个字节,8位,理论上可以表示256个字符,但是许多时候只谈128个。具体原因可以下去自行学习~)


    进一步优化代码:

    class Solution {
        public int lengthOfLongestSubstring(String s) {
            int n = s.length();
            int result = 0;
            int[] charIndex = new int[256];
            for (int left = 0, right = 0; right < n; right++) {
                char c = s.charAt(right);
                left = Math.max(charIndex[c], left);
                result = Math.max(result, right - left + 1);
                charIndex[c] = right + 1;
            }
    
            return result;
        }
    }
    

    执行结果:

    在这里插入图片描述

    我们发现优化后时间复杂度有了极大的改善!这里简单说一下原因,对于数组和hashmap访问时,两个谁快谁慢不是一定的,需要思考hashmap的底层实现,以及数据量大小。但是在这里,因为已知了待访问数据的下标,可以直接寻址,所以极大的缩短了查询时间。


    04、总结

    本题基本就到这里。最后要说的,一般建议如果要分析一道题,我们要压缩压缩再压缩,抽茧剥丝一样走到最后,尽可能的完成对题目的优化。不一定非要自己想到最优解,但绝对不要局限于单纯的完成题目,那样将毫无意义!


    我把我写的所有题解都整理成了一本电子书,每道题都配有完整图解。点击即可下载

    和小浩学算法

    展开全文
  • #include <...//暴力匹配法,时间复杂度比较高,从头到尾进行,分割出每一个子串子串之间进行比较,较大进行长度取值 //class Solution { //public: // void lengthOfLongestSubstring(string s...
  • 无重复字符的最长子串 问题描述 给定一个字符串,请你找出其中不含有重复字符 最长子串 长度。 解题思想 unordered_set使用: unordered_set<int> c1; //定义 c1.empty();//判断是否为空 c1.size(); //...
  •  最长公共子串问题基本表述为:  给定两个字符串,求出它们之间最长的相同子字符串长度。  最直接解法自然是找出两个字符串所有子字符串进行比较看他们是否相同,然后取得相同最长的那个。对于一个长度...
  • 无重复字符的最长子串 Python3 三种解法LeetCode 3.Longest Substring Without Repeating Characters 无重复字符的最长子串 Python3 两种解法暴力匹配滑动窗方法一滑动窗方法二 无重复字符的最长子串 Python3...
  • 最长子串: 匹配的字符需要连续,可能有多种结果。 解决思路:将输入字符串1看作行, 输入字符串2看作列,构成二位数组,然后将对角线匹配字符的值标记为1,计算满足条件的匹配字符个数即可。 基本思想: 空间换...
  • 题目描述:给定一个字符串,请你找出其中不含有重复字符 最长子串 长度。 方法一:暴力破解法 这题我第一次想到是暴力破解,即3个循环,类似于字符串匹配 public int lengthOfLongestSubstring(String s){ int...
  • 正确匹配的最长的括号子串

    千次阅读 2013-08-28 14:25:12
    分析:使用字符串进出栈来模拟括号的匹配,栈中保存没有进行匹配的字符串,扫描字符串,对于第i个字符,如果该字符为‘(’,则进栈,如果该字符为')',并且栈顶字符是‘(’,则进行匹配,否则不匹配,字符进栈。...
  • LastIndexOf(char,index) :从索引0开始到指定数值位置范围内查找最后一个匹配的的字符串位置 public static int LengthOfLongestSubstring(string s) { char[] arr = s.ToCharArray(); HashSet&...
  • 题目链接http://poj.org/problem?id=1743题目中介绍相差a...然后求解最长子串长度,然后答案+1便可,求解不重叠的最长子串长度,利用height数组求解出后缀数组最长公共前缀长度,然后二分枚举去判读答案(在满足答案
  • 遍历字符串,如果发生冲突则,更新left指针,也就是从上发生冲突下一个位置(left+idx+1)做为新窗口起点开启下一次匹配,right每次自增1 时间复杂度因为String.indexOf()时间复杂度为O(n*m):n是原串长度,m...
  • 【九度0J】 题目1535:重叠的最长子串 (扩展KMP算法)(滚动哈希算法--Rabin-Karp算法) 分类: 挑战程序设计竞赛---读书笔记 Algorithm...给定两个字符串,求它们前后重叠的最长子串的长度,比如"abcde"和“cd
  • 找出一个字符串中由同一个字符组成的最长子串   这是在百度知道中看到一个问题,感觉有点意思,就拿来练练手   思路也简单: 1.定义给个中间变量 2.用正则匹配有连续字符 3.如果匹配的字符比中间变量长就...
  • LCS问题就是求两个字符串最长公共子串的问题。解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1的序列,其对应的位置就是最长匹配子串的位置...
  • 2题意:输入n(2)个字符串集合(len == 60),询问n个字符串的最长公共子串,若长度相同,则输出字典序最小 3解题思路:通过传入字符串地址和长度枚举第一个串的子串在其它串中是否可以匹配,更新维护最优解vjudge...
  • 蛙蛙 上午发的一片 蛙蛙推荐:...算法描述:找出一个长字符串里的某个特定的子串出现的频率,匹配子串的上一个字符和下一个字符不需要紧紧相邻,只要满足下一个字符在当前字符的后面就行。算法要求:长字符串的宽度最
  • 最长公共子串

    2014-08-04 17:01:55
    LCS问题就是求两个字符串最长公共子串的问题。解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置. ...
  • 题目链接: 10456: 最长匹配子串 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 118 Solved: 22 [Submit][Status][Web Board] Description ...来字符串S中最长的完美串(S的子串)长度呢? I
  • 最长匹配子串(DP)(LCS)

    千次阅读 2018-12-03 08:40:22
    小乐乐有字符串str1,str2。 小乐乐想要给他们找朋友。 小乐乐想知道在这两个字符串中最多能匹配出多长的相同子串(可非连续)。...输出最长相同子串的长度。 示例1 输入 复制 asd ad 输出 复制 2 ...
  • 请找到一个最长的子串,使得其中0和1数量是相同 例1:“10101010” 结果就是其本身 例2:“0011110”结果是“0011” 变形:给定一个字符串,字符串只包含‘(’和‘)’,请找出一个最长的子串,使得该子串...
  • LCS问题就是求两个字符串最长公共子串的问题。解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1的序列,其对应的位置就是最长匹配子串的位置...
  • 5.最长回文子串

    2020-05-08 19:49:18
    5.最长回文子串 ...​ 一开始我的思路是这样的:将字符串s反转成s1,然后对s和s1进行最长公共子串的匹配。匹配的方法和昨天的1143.最长公共子序列一样: 如果s1[j] != s[i],选择三个方向的最大值 如果s1[j]
  • 分析:从较短的那个子串的长度串依次判断是不是长串的子串,即从将可能的最长公共子串开始比较,那么只要匹配到,一定是最长的子串。 int max_common_str(const string& s1, const string& s2) { string ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,548
精华内容 619
关键字:

最长子串的匹配