0
点赞
收藏
分享

微信扫一扫

最长不含重复字符的子字符串(剑指offer48、力扣3) Java滑动窗口

佳简诚锄 2022-02-03 阅读 37

一、题目描述

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

示例 1:

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


示例 2:

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


示例 3:

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

提示:

s.length <= 40000

二、思路讲解

        暴力方法,遍历字符串,以每一个字符作为开头,将它及后面的字符怼到HashSet中,如果怼不进去了,那就是重复了,此时集合的大小就是不重复的字串的大小。然后清空集合,再看下一个字符,直到遍历完整个字符串。效率较低。

 

三、Java代码实现 

class Solution {
    public int lengthOfLongestSubstring(String s) {

        int len = s.length();
        int index;
        HashSet<Character> set = new HashSet<>();
        int big = 0;
        for(int i=0; i<len; i++){
            index = i;
            set.clear();
			//把字符后的每一个字符怼进集合中,直到怼不进(说明重复了)或者遍历完了字符串
            while(index<len && set.add(s.charAt(index))){
                index++;
            }
            big = Math.max(big, set.size());
        }
        return big;
    }
}

四、时空复杂度分析 

        时间复杂度:        O(N^2)

        空间复杂度:        O(N) 

五、代码优化

        想想时间上的优化:能不能仅遍历一遍字符串呢?

        我们可以使用滑动窗口的思想。         

        再想想空间上的优化:能不能用常数级的空间呢?

        可以用HashMap,在ASCII码內长度最多为128,占用空间为常数级。

        具体思路是:创建一个哈希表,存储字符串中字符的下标,遍历字符串的同时维护一个滑动窗口,左指针j,右指针i,如果i处元素在哈希表中存在,则更新左指针至j、map.get(ch)两者之间的最大值。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character,Integer> map=new HashMap<>();
        int len = s.length();
        int j = 0;
        int big = 0;

        for(int i=0; i<len; i++){
            char ch = s.charAt(i);
            if(map.containsKey(ch)){
                j = Math.max(map.get(ch)+1, j);
            }
            map.put(ch, i);
            big = Math.max(big, (i-j+1));
        }
        return big;
    }
}

         时间复杂度:        O(N)

         空间复杂度:        O(1)

举报

相关推荐

0 条评论