剑指 Offer 48. 最长不含重复字符的子字符串

剑指 Offer 48. 最长不含重复字符的子字符串
剑指 Offer 48. 最长不含重复字符的子字符串
对于字符串区间类题目,一般可以考虑使用滑动窗口来求解问题。
在滑动窗口中一般设置l和r两个指针,l指针指向窗口的左边缘,r指针指向窗口的右边缘,整个窗口的大小为r - l + 1
在本题中,再用一个map或者set来查看窗口是否有重复数字,这里我为了方便一些用的是长为128的数组,正好可以存储下所有字符类型。
遍历到r位置的字符时,将r位置字符的次数加上1,若其正好为1,则说明之前的窗口中没有出现过r位置的字符,窗口扩大,r指针前移;
若r位置的字符出现次数大于1,则说明之前的窗口中出现过这个字符,窗口需要从左边缘开始收缩窗口,收缩时,需要满足l <= r && map[chars[r]] > 1,也就是确保窗口中不会有重复字符且不让窗口的左边缘超过右边缘。收缩的过程为:l指针前移,窗口中l指针位置指向的字符次数相应减少。此时窗口中没有重复字符了,继续扩大窗口r++。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length(), ans = 0;
        if(n == 0) return 0;
        if(n == 1) return 1;
        char[] chars = s.toCharArray();
        int l = 0, r = 0;
        int[] map = new int[128];
        while(r < n) {
            map[chars[r]]++;
            if(map[chars[r]] == 1) {
                // 窗口前移
                ans = Math.max(r - l + 1, ans);
                r++;
            } else if (map[chars[r]] > 1){
                // 窗口缩小
                while(l <= r && map[chars[r]] > 1) {
                    map[chars[l]]--;;
                    l++;
                }
                // 无重复字符了,进一步扩大窗口
                r++;
           }
        }
        return ans;
    }
}
上一篇:真正的门槛 - 全干工程师


下一篇:虚拟机克隆以后出现“需要整合虚拟机磁盘”的解决方法