Bootstrap

剑指Offer打卡day26——AcWing 61. 最长不含重复字符的子字符串

【题目描述】

在这里插入图片描述

AcWing 61. 最长不含重复字符的子字符串

【思路】

暴力做法:
for(i从0到n)
for(j从i到0)
统计子串[j,i]不包含重复字符的最大长度,也就是以i为右端点,j最远能往前走多远

暴力做法是O(n^2)的复杂度,进一步优化。通过暴力做法可以发现,i、j指针具有单调性。j往右移动,i不可能往左移动。
因此可以使用双指针, i在左, j在右。遍历扫描一遍。

class Solution {
    public int longestSubstringWithoutDuplication(String s) {
        if(s == null || s.length() == 0 ) return 0;
        int []hash = new int[26];
        char c[] = s.toCharArray();
        int res = 0, n = s.length();
        for(int i = 0, j = 0; j < n; j ++)
        {
            hash[c[j] - 'a'] ++;
            //右端发生有跟左边元素发生重复 左端i指针往右移动至不重复位置
            if( hash[c[j] - 'a'] > 1){
                while( i < j){
                    hash[c[i] - 'a'] --;
                    i ++;
                    if( hash[ c[j] - 'a' ] == 1) break;
                }
            }
            res = Math.max(res, j - i + 1);
            
        }
        return res;
    }
}

使用哈希表

class Solution {
    public int lengthOfLongestSubstring(String s) {
        /*
        双指针维护最长子串区间,i在左 j在右
        */
        if(s==null || s.length() == 0){
            return 0;
        }
        int i = -1, j = 0, n = s.length();
        char c[] = s.toCharArray();
        Map<Character, Integer> map = new HashMap<>(); //统计c[j]最后一次出现的索引
        int res = 0;
        while(j < n){
            if(map.containsKey(c[j])){  // [i, j]区域出现重复
                i = Math.max(i, map.get(c[j])); //  获取左指针最右能到达的地方(上一轮c[j]出现的位置)
            }
            map.put(c[j], j); // 最新的c[j]位置
            res = Math.max(res, j - i);
            j ++;
        }
        return res;
    }
}
;