LeetCode 精选 TOP 面试题(Java 实现)—— 无重复字符的最长子串

一、题目描述

1.1 题目
  • 无重复字符的最长子串

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

  • 示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
  • 示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
  • 示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
1.2 知识点
  • 哈希表
  • 双指针
  • 滑动窗口
1.3 题目链接

二、解题思路

2.1 自研思路

  这道题的解题思路比较明确,我是通过哈希表来记录每个字符最后出现的下标,当一个字符重复出现时,会及时更新该字符最后出现的下标,并更新最长子串的起始下标,该其实下标的作用其实就相当于滑动窗口算法中的窗口左边框,主要是为了防止出现对于 abba 这种形式字符串可能错误判断的情况。

2.2 示例思路

  官方提供的思想思路(窗口滑动的优化),其实跟我的算法是大致相同的,它对于普通的使用 HashSet 进行判重的逻辑进行优化,即当找到重复的字符时,可以立即跳过该窗口。也就是说,如果 s[j] 在 [i, j) 范围内有与 j′ 重复的字符,不需要逐渐增加 i ,而是可以直接跳过 [i,j′] 范围内的所有元素,并将 i 变为 j′+1(具体解题思路可见 LeetCode 官网,这里不再赘述)。

三、实现代码

3.1 自研实现
class Solution {
    public int lengthOfLongestSubstring(String s) {
        
        HashMap<Character, Integer> hashMap = new HashMap<>();
        int cur = 0, len = 0, start = 0;

        for(int i = 0; i < s.length(); i++){
            if (hashMap.containsKey(s.charAt(i)) && hashMap.get(s.charAt(i)) >= start){
                cur = i-hashMap.get(s.charAt(i));
                start = i-cur+1;
            } else {
                cur += 1;
                len = Math.max(len, cur);
            } 
            hashMap.put(s.charAt(i), i);
        }
        return len;
    }
}
3.2 示例代码
// 优化后的滑动窗口解法
public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length(), ans = 0;
        Map<Character, Integer> map = new HashMap<>(); // current index of character
        // try to extend the range [i, j]
        for (int j = 0, i = 0; j < n; j++) {
            if (map.containsKey(s.charAt(j))) {
                i = Math.max(map.get(s.charAt(j)), i);
            }
            ans = Math.max(ans, j - i + 1);
            map.put(s.charAt(j), j + 1);
        }
        return ans;
    }
}
发布了244 篇原创文章 · 获赞 32 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_40697071/article/details/103915753