LeetCode:3. 无重复字符的最长子串

道阻且长,行则将至。

算法,不如说它是一种思考方式


算法专栏: 123

题解目录

  • 一、[3. 无重复字符的最长子串](https://leetcode.cn/problems/longest-substring-without-repeating-characters/)
    • 解题
      • 1.双指针
      • 2.HashMap
      • 3.HashMap 2


一、3. 无重复字符的最长子串

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

  • 来源:力扣(LeetCode)

  • 难度:中等

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

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

解题

1.双指针

最容易得到的一个方法:以字符串每一个字符作为开头,来测试可以有多长的无重复。
也就是双指针方法,左指针一直指向字符开头,右指针遍历字符,当有出现重复时,左指针移动,右指针再次遍历。

class Solution {
    public static int lengthOfLongestSubstring(String s) {
        int max_str=0;
        if(s.length()==0||s.length()==1)return s.length();
        Set<Character> strSet = new HashSet<Character>();
        int n = s.length();
        int rk = -1;
        for (int i = 0; i < n; ++i) {
            if (i != 0) {//去掉这个元素 移动左指针
                strSet.remove(s.charAt(i - 1));
            }
            while (rk + 1 < n && !strSet.contains(s.charAt(rk + 1))) {//移动右指针
                strSet.add(s.charAt(rk + 1));
                ++rk;
            }
            if(rk - i + 1>max_str)
                max_str = rk - i + 1;
        }
        return max_str;
    }
}

LeetCode:3. 无重复字符的最长子串_第1张图片

而这样其实做了许多重复工作。例如一个字符串:a b c b a d,就知道从b开始没必要了。为了这样,我们就像找到一个回溯的方法。于是可以用HashMap来记录字符在字符串的索引来帮助回溯。

2.HashMap

对于出现的重复字符,使用i=strMap.get(s.charAt(i));来直接回溯,也就是前面的左指针移动,然后把HashMap清空,代表右指针回归,重新遍历。

class Solution3{
    public static int lengthOfLongestSubstring(String s) {
        int max_str=0;
        if(s.length()==0||s.length()==1)return s.length();
        Map<Character,Integer> strMap=new HashMap<>();
        int len=0;

        for (int i = 0; i < s.length(); i++) {
            if(!strMap.containsKey(s.charAt(i))){// 没有重复元素
                strMap.put(s.charAt(i),i);
                len++;
            }
            else{
                if(len>max_str)max_str=len;
                len=0;
                i=strMap.get(s.charAt(i));
                strMap.clear();
            }
        }
        if(len>max_str)max_str=len;
        return max_str;
    }
}

LeetCode:3. 无重复字符的最长子串_第2张图片

3.HashMap 2

发现清空HashMap也是没必要的,而且造成浪费,于是思考一种更快捷的回退方法。
就是说在重复的元素前面的才需要去除,而且右指针不用回归,不用重复遍历。

class Solution3{
    public static int lengthOfLongestSubstring(String s) {
        int max_str=0;
        if(s.length()==0||s.length()==1)return s.length();
        Map<Character,Integer> strMap=new HashMap<>();
        int len=0;

        for (int i = 0; i < s.length(); i++) {
            if(!strMap.containsKey(s.charAt(i))){// 没有重复元素
                strMap.put(s.charAt(i),i);
                len++;
            }
            else{
                if(len>max_str)max_str=len;
                int k=strMap.get(s.charAt(i));
                len=i-k-1;
                while(k>=0&&strMap.containsValue(k)){//只需要移除这些元素就可以了
                    strMap.remove(s.charAt(k));
                    k--;
                }
                i--;
            }
        }
        if(len>max_str)max_str=len;
        return max_str;
    }
}

LeetCode:3. 无重复字符的最长子串_第3张图片


豫章故郡,洪都新府。星分翼轸,地接衡庐。襟三江而带五湖,控蛮荆而引瓯越。
—— 滕王阁序

返回第一页。☝


☕物有本末,事有终始,知所先后。

☝☝☝☝☝我的CSDN☝☝☝☝☝☝

你可能感兴趣的:(#,Java算法,leetcode,算法,职场和发展)