无重复字符的最长子串

题目

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

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

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

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

示例 4:
输入: s = ""
输出: 0

提示:0 <= s.length <= 5 * 104,s由英文字母、数字、符号和空格组成

来源:力扣(LeetCode),链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

找出最长无重复字符子串:从这里体现我们想要找到答案必然面临着全局遍历。
确定最长子串的区间位置,最直接想法是通过两个指针leftright遍历整个子串计算区间最长跨度。
从起始位置开始,right指针不断往前推进,并每前进一步都判断当前right指向的字符,是否在之前[left,right)区间内的字符集合内部。若不存在,证明最长无重复字符还未到right指针继续前进;若存在,当前区间[left,right)已到达最长无重复字符。
这里产生几个问题,如何快速判断right指向的字符是否已存在在区间[left,right)中?left指针指向在出现重复字符时如何推进?

如何快速判断right指向的字符是否已存在在区间[left,right)中?

快速判断根源在于快速查找,在我们众多查找算法中,只有hash集合和数组能够在一定条件下做到O(1)时间复杂度,而且数组结构必须知道坐标位置方能作为快速选择。因此,这里选着hash作为承载数据结构。

left指针指向在出现重复字符时如何推进?

出现重复字符时,证明当前区间[left,right-1)为无重复字符(right指向第一个重复字符),left往前推进到重复字符位置。

查找动态演示

待续。。。

编码实现

public int lengthOfLongestSubstring(String s) {
        if(s == null || s.length() <= 0){
            return 0;
        }
        // 采用双指针法进行遍历字符串,找出最长无重复子串
        int left = 0;
        int right = 0;
        // 承载非重复字符下标位置,用于判重
        HashMap<Character, Integer> map = new HashMap<>();
        char[] charArray = s.toCharArray();
        int res = 0;
        while(right < charArray.length){
            if(map.get(charArray[right]) != null){
                // 当出现重复时,需要往前推移左标坐标
                // 比较最大值,是因为随着坐标往前移动,若后面出现字符在前方出现过了,坐标也不应该往前移动
                left = Math.max(map.get(charArray[right]), left);
            }
            // 比较最长字符串长度
            res = Math.max(res, right - left + 1);
            // 这里存在该字符下一位置,表明该字符之前都未出现重复字符;
            // 若出现重复字符应该在该字符下个字符位置重新计算
            map.put(charArray[right], right + 1);
            right++;
        }

        return res;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容