欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

leetcode打卡10:题号:3 无重复字符的最长子串,给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

程序员文章站 2022-05-12 22:21:30
...

题目:

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

示例 1:

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

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

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

题目解析一(暴力解法):

1.暴力解法其实就是不断的取子串进行判断是否有重复字符
2.所以标准答案给出了一个方案,定义一个allUnique(s,i,j)方法去判断在s中截取i到j的子串中是否存在重复
3.但是实际上这种做法非常的耗时,并且在leetcode上运行会报运行时间过长的问题

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int ans = 0;
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j <= n; j++)
                if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
        return ans;
    }

    public boolean allUnique(String s, int start, int end) {
        Set<Character> set = new HashSet<>();
        for (int i = start; i < end; i++) {
            Character ch = s.charAt(i);
            if (set.contains(ch)) return false;
            set.add(ch);
        }
        return true;
    }
}

题目解析二(自己的算法):

1.这个方法是我自己写出来的,写之前我也不知道其实这道题最优的解法是使用滑动窗口,但是我写出来之后发现我的这种方法集成了暴力算法和滑动窗口,虽然不如滑动窗口,但是比暴力解法好多了
2.设置两个初始化索引 i=0,j = i + 1,每次先将s【i】传入hashmap(实际上使用hashset就可以),之后开始从s【j】判断map中是否存在重复字符,如果不重复,就将s【j】传进去(其实就是判断从i到j的窗口中是否重复),然后j++
3.如果发现s【j】已经重复了,那么就记录窗口大小,然后 i++ ,j = i+1;这样就又重新开始了新的一遍遍历,第二次遍历就从i = 1, j=2,j开始往后走开始遍历。
leetcode打卡10:题号:3 无重复字符的最长子串,给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

public static  int lengthOfLongestSubstring(String s) {
        if(s.equals("") ) return 0;
        // if(s.length() == 0) return 0;
        int i = 0;
        int j = 0;
        int result = 1;
        for(i = 0; i < s.length(); i++){
            int temp = 1;
            HashMap map = new HashMap();
            map.put(s.charAt(i),i);
            for(j = i + 1; j < s.length(); j++){
                if(!map.containsKey(s.charAt(j))){
                    map.put(s.charAt(j),j);
                    temp = temp + 1;
                }else{
                    break;
                }
            }
            if(temp > result) result = temp;

        }
        return result;
    }

题目解析三(滑动窗口解法)

1.这个解法其实就是我自己写的方法的优化解法,我刚刚的解法还是可以优化的,具体优化的地方就在于,我每次的窗口是[i,j),每次走到重复的地方跳出,我又重新将窗口变成了[i+1,i+2),到这里我又要重新将map清空,然后又要从s【i+1】开始往map里面存值,但是实际上刚刚的清空的map中都会已经存有从s【i+1】开始的值,这样空间上和时间上都浪费了
2.所以我的窗口从[i,j)找到了重复的地方时,为了避免将set(这里使用set)清空,我将窗口直接变成[i+1,j),将set中的s【i】取出,这样的话就节省了我重新从s【i+1】开始存储的时间。
leetcode打卡10:题号:3 无重复字符的最长子串,给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

public int lengthOfLongestSubstring1(String s) {
        if(s.equals("") ) return 0;
        int i = 0;
        int j = 0;
        int length = s.length();
        int result = 0;
        HashSet set = new HashSet();
        while(i < length && j < length ){
            if(!set.contains(s.charAt(j))){ //无重复的就存储 区间右端点右移
                set.add(s.charAt(j));
                j += 1;
                result = Math.max(result,j-i);//取区间长度
            }else{//重复了 区间左端点右移

                set.remove(s.charAt(i));
                i += 1;
            }
        }
        return result;
    }

这里就比我刚刚的简单多了,省了每个新遍历的存储时间和判断时间。

题目分析四(最优化解法):

1.对于第三解法的滑动窗口解法如果已经弄懂了话,那么其实我们很清楚,当我们在[i,j)中找到了 s【j’ 】与 s【j】相同的话,我们其实可以直接将窗口定位到[j’+1,j),为什么这么做呢,因为 如果用上面的方法,[i,j’]中的元素我们还要一直和s[j]进行判断,不断的将区间左端点右移,直到移到j’+1,所以我们完全可以用空间换时间的想法,直接用索引定位 j’ 的位置,直接将区间定位到[j’+1,j)
2.但是在这里我们用的是map,并且不会进行擦除元素,也就是说当我们定位到[j’+1,j)之后,后面的字符在判断重复的时候可能会判断到区间之前的元素,这里要进行一个判断即可

 public int lengthOfLongestSubstring4(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;

    }

总结:
1.String字符串取长度的方法是length();
2.字符串判断为空串是用equals,用==判断不准,在我的IDEA中是可以的,但是在leetcode上不行
3.如果字符不为空,那么最小长度为1
4.hashset的判断是否存在方法为contains
5.取字符串的字符用charAt方法
6.map的get方法取到的是object对象,要进行强制转换

相关标签: leetcode打卡