LeetCode 3. Longest Substring Without Repeating Characters

问题描述

  • Given a string, find the length of the longest substring without repeating characters.
  • Examples:
    Given “abcabcbb”, the answer is “abc”, which the length is 3.
    Given “bbbbb”, the answer is “b”, with the length of 1.
    Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

问题分析

  • 方法一:窗口
    用双指针形成一个窗口,并用count[]数组来统计窗口内数字的次数,若 right 位置的下一位置在count[]数组中的次数为1,说明不能入窗,则窗口左侧减数,并更新count。若次数为0,说明可以入窗,那么窗口加数,并更新count 以及 maxLength.
  • 方法二:优化版窗口
    用index[i] 存储 (ch) i 在已遍历数组中的最后一个位置的下一位置。所以,如果考虑将 right位置元素入窗时,必须改变left值,让当前窗口的 left 为 原left 与 s[right] 的最后出现位置的下一位置,这样才能保证right入窗不会造成重复。然后统计长度,并更新s[left]的index,继续将下一个left入窗。

经验教训

  • 双指针窗口问题
  • 判重也可用HashSet,但是不如count

代码实现

  • 滑动窗口模板做法
    public int lengthOfLongestSubstring(String s) {
        if (s == null || s == "") {
            return 0;
        }
        int[] map = new int[256];
        int left = 0;
        int right = 0;
        int length = s.length();
        int maxLength = 0;
        while (right < length) {
            ++map[s.charAt(right)];
            while (map[s.charAt(right)] > 1) { //如果right位置元素的入窗导致出现重复,那么便缩小窗口,左侧出数,一直等到right元素不会有重复为止
                --map[s.charAt(left)];
                ++left;
            }
            //统计当前窗口长度
            maxLength = Math.max(maxLength, right - left + 1);
            //继续扩大窗口
            ++right;
        }
        return maxLength;
    }
  • 窗口
    public int lengthOfLongestSubstring(String s) {
        if (s == null || s == "") {
            return 0;
        }
        //统计次数
        int[] count = new int[256];
        //初始化窗口
        int left = 0;
        int right = -1;
        int maxLength = 0;
        int length = s.length();
        while (left < length) {
            if (right + 1 < length && count[s.charAt(right + 1)] == 0) { //下一元素能够入窗
                //更新次数
                count[s.charAt(++right)]++;
                //更新maxLength
                maxLength = Math.max(maxLength, right - left + 1);
            }else {
                //下一元素不能入窗(要么right已经走到末尾,要么下一元素若入窗会造成重复),则左侧数字出窗,并更新次数
                count[s.charAt(left++)]--;
            }
        }
        return maxLength;
    }
  • 优化版窗口
    public int lengthOfLongestSubstring(String s) {

        if (s == null || s == "") {
            return 0;
        }
        //index[i]存储 (char) i 出现的的最后一次位置的下一位置,所以初始化为0
        int[] index = new int[256];
        //初始化窗口
        int left = 0;
        int right = 0;
        int maxLength = 0;
        int length = s.length();
        while (right < length) {
            //为了防止重复,需要根据当前right位置字符来重新定位left位置
            left = Math.max(left, index[s.charAt(right)]);
            //计算长度
            maxLength = Math.max(maxLength, right - left + 1);
            //设置right处的index
            index[s.charAt(right)] = right + 1;
            right++;
        }
        return maxLength;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值