力扣java最长无重复_力扣(LeetCode) 3. 无重复字符的最长子串

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

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

示例 1:

输入: "abcabcbb"

输出: 3

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

示例 2:

输入: "bbbbb"

输出: 1

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

示例 3:

输入: "pwwkew"

输出: 3

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

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

来源:力扣(LeetCode)

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

为了找到不重复的最大子串,我们每次添加一个字母,然后判断最后一个字母是否在前面的字母中出现,只要未出现,那么最大长度+1,如果出现,那么我们就要把与最后一个字母重复的字母后面开始计算最大长度。

为此,我们可以设计2次循环,外循环p循环字母长度,每次字母长度+1,内循环新增的字母是否重复。定义变量start指示内循环开始位置。如下图:

外指针p一直循环到E时,内循环未发现重复数据,此时最大长度 = p-q +1 ,如下图

继续循环,外指针循环到第二个L时,内指针循环到第一个L时,发现重复数据,重新定义内循环开始位置q+1。

相关代码如下:

public int lengthOfLongestSubstring(String s) {

// q 内循环开始位置 int start = 0;

int maxLen = 0;

// p -外循环字符串S的长度次,每次长度+1 for(int p=0;p

// q -内循环 从start开始,p的前面一个位置结束 for(int q=start;q

// 发现q的当前位置有重复数据,内循环从q的下一个位置开始 if(s.charAt(q) == s.charAt(p)){

start = q+1;

break;

}

}

//每次内循环结束,获取最大长度 maxLen = maxLen > (p-start +1) ? maxLen : (p-start +1);

}

return maxLen;

}

复杂度分析:

时间复杂度:O(n*n) 使用了嵌套的2次for循环。

空间复杂度:O(1) 定义了4个变量,start、maxLen、p、q

代码优化

从上述代码可以看出,代码的时间复杂度为O(n*n),效率不是很高,而且第二个for循环仅仅判断字母是否重复出现,而在java中有个时间复杂度为O(1)的算法查找字母是否出现过,没错,就是HashMap,通过空间换时间,提高效率。修改后的代码如下:

public int lengthOfLongestSubstring(String s) {

int start = 0;

int maxLen = 0;

Map map = new HashMap<>();

// p-外循环字符串S的长度次,每次长度+1 for (int p = 0; p < s.length(); p++) {

// 判断字母是否在Map中存在,如果存在,则重新定义开始位置 // 判断重复位置后一位与开始位置的值,取最大值作为开始位置 if (map.containsKey(s.charAt(p))) {

start = Math.max(start, map.get(s.charAt(p))+1);

}

// 将字母保存到map中,key 为字母,value为索引 map.put(s.charAt(p), p);

maxLen = Math.max(maxLen, p-start + 1);

}

return maxLen;

}

复杂度分析:

时间复杂度:O(n) 只循环一次

空间复杂度:O(n) 额外申请hashmap空间

滑动窗口

其实细心的小伙伴可能已经发现,优化之后的代码就是滑动窗口的算法实现了,下面简单介绍一下滑动窗口的示例图:第一次循环,只有一个元素,不重复长度为1第2次循环,有2个不重复元素,不重复长度为2第3次循环,有3个不重复元素,不重复长度为3第4次循环,发现L元素重复,窗口开始位置为重复元素最大坐标的下一个位置,不重复长度为1第5次循环,有2个不重复元素,不重复长度为2第6次循环,有3个不重复元素,不重复长度为3第7次循环,发现O元素重复,窗口左边位置滑动到重复位置的下一个位置,不重复长度为2第8次循环,有3个不重复元素,不重复长度为3第9次循环,发现L元素重复,但是窗口左边的位置的索引大于前面L元素的最大索引,所以开始位置还是W元素第10次循环,有5个不重复元素,最大长度为5

好了,通过演示,明白了滑动窗口的原理,最主要的是确定左边窗口的位置。现在回头看看第二段代码,是不是更容易理解了呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值