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

Posted 52fhy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——3. 无重复字符的最长子串相关的知识,希望对你有一定的参考价值。

难度: 中等

题目

Given a string, find the length of the longest substring without repeating characters.
给定一个字符串,请你找出其中不含有重复字符的?最长子串?的长度。

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

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

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

示例 4:
输入: "dvdf"
输出: 3
解释: 因为无重复字符的最长子串是 "vdf",所以其长度为 3。注意不是2。

php

暴力解法

1、定义一个方法 isUnique($s, $start, $end) 给定字符串和开始、结束标识,计算里面是否包含重复字符,如果是返回false,否则true。
2、对字符串s遍历 i*j趟,生成字串使用isUnique判断是不是重复,如果不是,则更新 返回值 max(最长子串?的长度)。

相当于遍历 N^3次:

//判断一个字符串里面是否有重复字符
function isUnique($s, $start, $end) 
    $map = [];
    $len = $end-$start+1;
    $sub_str = substr($s, $start, $len);
    for ($i = 0; $i < $len; $i++) 
        if (in_array($sub_str[$i], $map) ) 
            return false;
        
        $map[] = $sub_str[$i];
    
    
    return true;


/**
 * @param String $s
 * @return Integer
 */
function lengthOfLongestSubstring($s) 
    $len = strlen($s);
    $max = 0;
    if ($len > 0) 
        $max = 1;
    
    
    for ($i = 0; $i < $len; $i++) 
        for ($j = $i + 1; $j < $len; $j++) 
            if ($this->isUnique($s, $i, $j)) 
                if ($j - $i + 1 > $max) 
                    $max =  $j - $i + 1;  
                
                
        
    
    
    return $max;

时间复杂度为O(n^3)。

滑动窗口

上面的暴力解法实在是太慢了。以字符串ababc为例,ab出现了2次,那么对于子串abaababababc的计算是可以省略的,可以将i直接往后移动。

我们可以使用一个集合(Set)存储遍历过的值,如果发现即将要遍历的字符串已经存在set里,那么可以将i直接往后移动,并将已存在的字符从集合里删除;如果发现即将要遍历的字符串不在set里,则放在set里,并将j往后移动,同时更新返回值 max(最长子串?的长度)。

function lengthOfLongestSubstring2($s) 
    $len = strlen($s);
    $max = 0;
    $i = $j = 0;
    $set = [];

    while ($i< $len && $j < $len) 
        if (!in_array($s[$j], $set)) 
            $set[] = $s[$j++];
            $max = max($max, $j - $i);
         else 
            //出现过,说明符合要求的子字符串已经结束,删掉子字符串开始的字符
            //由于php没有java的hashSet结构,下面是模拟删除set里的值
            unset($set[array_keys($set, $s[$i++])[0]]);
        
    

    return $max;

时间复杂度为O(2n)=O(n)。

优化的滑动窗口

function lengthOfLongestSubstring3($s) 
    $len = strlen($s);
    $max = 0;
    $i = $j = 0;
    $map = [];

    //dvdf
    while ($i< $len && $j < $len) 
        if (array_key_exists($s[$j], $map)) 
            //发现重复字符,key移动到不重复字符的位置
            //例如dvdf,第三次发现d,已经重复,第一个的d的索引是0,那么i需要往下移动
            $i = max($map[$s[$j]] + 1, $i); 
        

        $map[$s[$j]] = $j; //key存储字符,value存储某个不重复字符的索引
        $max = max($max, $j - $i + 1); 

        $j++;
    

    return $max;

来源

链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters

以上是关于Leetcode——3. 无重复字符的最长子串的主要内容,如果未能解决你的问题,请参考以下文章

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

LeetCode 无重复字符的最长子串

[LeetCode]无重复字符的最长子串

LeetCode——无重复字符的最长子串

leetcode-无重复字符的最长子串

LeetCode--003--无重复字符的最长子串