zoukankan      html  css  js  c++  java
  • 【算法剖析】求字符串中无重复字符的最长字串

    1、问题描述

      这个问题来自leetcode中的Longest Substring Without Repeating Characters,诚如标题所述,我们需要寻找的是在一个字符串中,没有重复字符的最长字串。我们假定字符串中的字符只由$a$~$z$这26个字符构成。例如,对于字符串"$abcabcbb$",它的无重复字符最长字串是"$abc$",长度为3;对于字符串"$bbbb$",它的无重复最长字串是$b$,长度为1。

    2、算法一

      我们能够立即想到的,最原始的算法就是,从字符串的每一个位置开始构造字串,并逐渐增大字串长度,直到碰到一个已经出现在这个字串中的字符为止,这样对于长度为$n$的字符串而言,经过$n$次遍历即可求得最长的无重复字符字串。实际上,考虑到构成字符串的字母表大小只有26,每次遍历最多也只需进行26次增长子串的操作,这个算法的整个时间复杂度为$O(26n)$。这个算法很简单也很好理解,不再给出详细代码。

    3、算法二

      算法二能够将时间复杂度缩小到$O(n)$,即只遍历一遍字符串即可。它主要基于一个思想:当我们在构建子串的时候,如果遇到了一个重复字符,那么我们可以使遍历跳跃一定“距离”,直接忽略掉不必要的搜索。对于一个字符串$A=a_{0}a_{1}a_{2}a_{3}...a_{n-1}$,我们正在构造的字串是$B=a_ja_{j+1}...a_k$,接下来一个字符是$a_{k+1}$,但是它与当前$B$中的某一字符$a_{k'}$相同。那么对于那些所有以$a_i$,$(j+1 le i < k)$开头的无重复字符最长字串的长度一定小于$B$的长度。例如,对于字符串$A=$"$abcdcef$",$B=$"$abcd$",当前长度为4,下一个字符是$c$,而它与$b_3$相同,那么在$A$中,以$a_1,a_2,a_3$开头的无重复字符最长字串,相对于$B$,“更早地”遇到了重复字符$c$,它们的长度都要小于$B$的长度。

      为了实现算法二,我们需要额外使用一个大小为26的数组$pos$以及一个变量$basePos$,$pos$用来记录当前情况下,每个字符最近出现的那个位置,而$basePos$用来记录所增长的子串的开始位置。初始情况下,$basePos=0$,表示第一个所增长的那个子串开始于位置0,$pos$中的每个元素都初始为-1。对于当前的字串,我们如何判断下一个字符是否已经出现在了当前字串中呢?例如,对于字符$a$,我们检查$pos[0] le basePos$是否成立,成立的话,则说明$a$已经出现在当前字串中,弄明白需要搞清楚$pos$与$basePos$的含义。

      我们使用一个例子来说明这个过程。


    初始情况

    Step:1

    Step:2

    Step:3

    Step:4

    Step:5

    注意,这里是由于pos['c'-'a']=2>basePos,也就是第二个c与前面的c重复了。

    Step:6

    Step:7


    下面我们给出代码,我们需要处理某些特殊情况,例如输入字符串为空串等等。

        int lengthOfLongestSubstring(string s) {
            int pos[26];
            int i;
            
            for(i=0;i<26;i++)
            {
                pos[i]=-1;
            }
            int basePos=0;
            int maxLength=-1;
            for(i=0;i<s.length();i++)
            {
                if(pos[s[i]-'a']<basePos)
                {
                    pos[s[i]-'a']=i;
                }
                else 
                {
                    if(maxLength==-1||i-basePos>maxLength)
                        maxLength=i-basePos;
                    basePos=pos[s[i]-'a']+1;
                    pos[s[i]-'a']=i;
                }
            }
            if(s.length()-basePos>maxLength||maxLength==-1) maxLength=s.length()-basePos;
            return maxLength;
        }
    算法二
  • 相关阅读:
    C 标准库
    C 标准库
    C 标准库
    C 标准库
    Chrome内核保存为mhtml(单网页)
    C 标准库
    C 标准库
    【转】AOP
    [转]控制反转与依赖注入模式
    [转]乐观锁、悲观锁、死锁的区别
  • 原文地址:https://www.cnblogs.com/XjChenny/p/3163949.html
Copyright © 2011-2022 走看看