无重复字符的最长子串

题目

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

leetcode链接

示例

示例 1:

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

示例 2:

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

思路

  • 最容易想到是暴力法,每遍历一个字符,就生成一个set,然后往后遍历,看以当前为底的字符最长多少不重复
  • 进阶一点是滑动数组,思想就是保证滑块内的字符都不重复
  • 这里使用一个map保存字符和他的数组位置,使用一个int类型的变量保存滑动数组的左边界,滑动数组的有边界是当前遍历的字符的下标
  • 每遍历一个元素时,看map中是否包含该元素,如果不包含,那么滑动数组左边界不需要修改,直接把该字符和下标放入map中
    • 如果包含,就分情况讨论了,一个是得到这个map中得到的元素的下标在left左边,说明滑动数组已经不包含该元素了,修改map中该字符的下标更新为最新的。
    • 如果map中得到的元素下标在left右边,那么left需要修改为得到的这个下标加一,然后将该map中的元素的下标更新.
    • left = Math.max(left, map.get(charArray[i]) + 1); 就是这段代码,实现了滑动数组的效果
  • 计算子串长度。i - left + 1

代码实现

//滑动数组
public int lengthOfLongestSubstring(String s) {
    int result = 0;
    char[] charArray = s.toCharArray();
    Map<Character, Integer> map = new HashMap<>();
    int left = 0;
    for (int i = 0; i < s.length(); i++) {
        if (map.containsKey(charArray[i])) {
            left = Math.max(left, map.get(charArray[i]) + 1);
        }
        map.put(charArray[i], i);
        result = Math.max(result, i - left + 1);
    }
    return result;
}
//暴力法
public int lengthOfLongestSubstring01(String s) {
    int result = 0;
    char[] charArray = s.toCharArray();
    for (int i = 0; i < charArray.length; i++){
        HashSet<Character> set = new HashSet<>();
        set.add(charArray[i]);
        int temp = 1;
        while ((temp + i < charArray.length) && !set.contains(charArray[i + temp])) {
            set.add(charArray[i + temp]);
            temp++;
        }
        result = Math.max(result, temp);
    }
    return result;
}

posted on 2024-11-06 14:27  oYYo  阅读(1)  评论(0编辑  收藏  举报

导航