给一个字符串,找出最长的非重复子字符串长度
例如:
输入:”abcabcbb”
输出:3
答案是”abc”,所以长度为3
方法一:暴力穷举
这种方法思路比较简单,就是循环遍历整个字符串,依次找出最开始的非重复子字符串,然后得到其中的最大值进行返回。
以下是我当时使用暴力穷举法的代码。
1 | class Solution { |
在leetcode的官方solution中,暴力穷举法的代码如下:
1 | public class Solution { |
相对而言比我的代码更为简洁。
复杂度分析:
时间复杂度:$O(n^3)$
空间复杂度:$O(min(n,m))$
方法二:滑动窗口法
滑动窗口法在数组或者字符串中的问题中是一种十分普遍的算法,窗口范围通常是由数组(或字符串)的某一个开始位置和另一个结束位置定义的,例如,窗口$[i,j)$(左闭右开)。
窗口一般是朝一个方向移动,例如,我们将窗口$[i,j)$向右边移动一个元素,则窗口现在为$[i+1,j+1)$
对于我们的问题,我们可以使用HashSet来存储我们的窗口(字符集)$[i,j)$(初始位置$i=j$),然后我们向右移动$j$直到新增的元素在原来的窗口(HashSet)中存在或者移动到最右边。完成后,我们就得到了开始位置为$i$的最大不重复窗口,如果我们遍历所有的$i$,取最大值就是答案。
1 | public class Solution { |
复杂度分析:
时间复杂度:$O(2n) = O(n)$,最坏情况是遍历所有的$i$和$j$。
空间复杂度:$O(min(n,m))$
方法三:优化滑动窗口法
我们可以使用Map来存储字符串以及它的索引位置,然后当我们发现有重复的字符时我们可以跳过中间的所有字符。
因为如果$s[j]$(表示$s$的第$j$到最后字符串)在位置$j’$有字符与窗口$[i, j)$中重复,则我们无需一个位置一个位置增加$i$,而是可以直接跳过$[i, j’]$中的所有元素。
代码如下:
1 | public class Solution { |