[LeetCode

来源:互联网 发布:怎么在淘宝上购物流程 编辑:程序博客网 时间:2024/06/06 02:06

1 问题

Given a string, find the length of the longest substring without repeating characters.
Examples:
Given “abcabcbb”, the answer is “abc”, which the length is 3.
Given “bbbbb”, the answer is “b”, with the length of 1.
Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

2 分析

定理1:长度为n的字符串的所有子字符串的数量为: n(n+1)2

  • 证明:以字符串 “abcde” 为例:
    以第一个字符 ‘a’ 开头的子字符串个数为 5
    以第二个字符 ‘b’ 开头的子字符串个数为 4
    以第三个字符 ‘c’ 开头的子字符串个数为 3
    以第四个字符 ‘d’ 开头的子字符串个数为 2
    以第五个字符 ‘e’ 开头的子字符串个数为 1
    根据以上规律可以得出长度为n的字符串的所有子字符串的个数是1+2+3+...+n=O(n2)

因此,如果列举出所有的子字符串后再判断最大的长度的子字符串,那么效率不够高。通过观察不含重复字符的子字符串的特征有:
Si,j 表示以i为起点,以j为终点的不含有重复字符的子字符串(j对应的字符不在子串中, 例如”abcde”中,S1,3表示 “ab”), Si,j+1的长度与Si,j的长度有如下的关系:

  • 如果字符S(j)包含在Si,j中, 那么Si,j+1因为含有重复字符而不符合题目的要求
  • 如果字符S(j)不包含在Si,j中, 那么Si,j+1的长度等于Si,j的长度+1

这样就可以用滑动窗口方法,处理这一类字符串、数组问题。
滑动窗口方法包括两个主要操作

  • 向左(右)扩展
  • 向左(右)收缩
    具体做法请参考:what is sliding window algorithm

3 伪代码

  • left, right 代表窗口的左右边界,将 left, right 初始化为0
  • 初始化空哈希表 hs,表的键为left,right表示的窗口中不重复的字符值
  • 初始化maxLen=0, 表示最长的不重复子串的长度
  • 执行以下循环,循环的结束条件是:right >= len(s),s表示题目给出的字符串
    • 判断s(j)是不是在hs中:
    • 如果是,那么将s(left)hs中删除, 并执行left=left+1,将窗口左边界向右收缩
    • 如果否,那么将s(right)加入hs中, 并执行right=right+1, 将窗口右边界向右扩展, 同时更新maxLen = right - left
  • 在循环结束后,返回maxLen

时间复杂度:在算法执行的过程中,left,right分别遍历一遍s,故时间复杂度是O(2n)

4 Java代码

public class Solution {    public int lengthOfLongestSubstring(String s) {        int n = s.length();        Set<Character> set = new HashSet<>();        int ans = 0, i = 0, j = 0;        while (i < n && j < n) {            // try to extend the range [i, j]            if (!set.contains(s.charAt(j))){                set.add(s.charAt(j++));                ans = Math.max(ans, j - i);            }            else {                set.remove(s.charAt(i++));            }        }        return ans;    }}
0 0
原创粉丝点击