LeetCode刷题之无重复字符的最长子串

LeetCode刷题之无重复字符的最长子串

  • 无重复字符的最长子串(Longest Substring Without Repeating Characters)
    • 题目
    • 代码
    • 官方解法
      • 方法一:暴力法
      • 方法二:滑动窗口
      • 方法三:优化的滑动窗口
  • 其他
    • 滑动窗口

无重复字符的最长子串(Longest Substring Without Repeating Characters)

题目

LeetCode刷题之无重复字符的最长子串_第1张图片

代码



    /**
    * @ClassName LongestSubstring
    * @Description TODO 不含有重复字符的最长子串$
    * @Author charlesYan
    * @Date 2020/3/11 15:06
    * @Version 1.0
    **/
    public class LongestSubstring {
     

        public static int lengthOfLongestSubstring(String s){
     
            //非空校验
            if (s == null) {
     
                return 0;
            }
            //将字符串转成字符数组
            char[] chars = s.toCharArray();
            String substring = "";
            StringBuilder sb = null;
            //遍历字符串
            for (int i = 0; i < chars.length; i++) {
     
                //初始化起始字符串
                sb = new StringBuilder();
                sb.append(chars[i]);
                for (int j = i+1; j < chars.length; j++) {
     

                    //子串若包含下一个字符跳出改层循环
                    if (sb.toString().indexOf(chars[j]) != -1) {
     
                        break;
                    }
                    sb.append(chars[j]);
                }
                //判断如果当前子串长度大于已获取最长子串长度,则当前子串为最长子串
                substring = sb.toString().length() > substring.length() ? sb.toString():substring;
            }
            System.out.println(substring);
            return substring.length();
        }

        public static void main(String[] args) {
     
            String str = "pwwkew";
            int length = lengthOfLongestSubstring(str);
            System.out.println("最长非重复子串长度:" + length);

        }
    }


官方解法

方法一:暴力法

  • 解题思路

    LeetCode刷题之无重复字符的最长子串_第2张图片

  • 源码

    
        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;
            }
        }
    
    
    
  • 复杂度分析

    LeetCode刷题之无重复字符的最长子串_第3张图片

方法二:滑动窗口

  • 解题思路

    LeetCode刷题之无重复字符的最长子串_第4张图片

  • 源码

    
        public class Solution {
           
            public int lengthOfLongestSubstring(String s) {
           
                int n = s.length();
                Set<Character> set = new HashSet<>();
                int ans = 0, i = 0, j = 0;
                while (i < n && j < n) {
           
                    // try to extend the range [i, j]
                    if (!set.contains(s.charAt(j))){
           
                        set.add(s.charAt(j++));
                        ans = Math.max(ans, j - i);
                    }
                    else {
           
                        set.remove(s.charAt(i++));
                    }
                }
                return ans;
            }
        }
    
    
  • 复杂度分析
    LeetCode刷题之无重复字符的最长子串_第5张图片

方法三:优化的滑动窗口

  • 解题思路(HashMap)
    方法三思路分析

  • 源码(HashMap)

    
       public class Solution {
           
            public int lengthOfLongestSubstring(String s) {
           
                //定义最大不重复字符串长度ans
                int n = s.length(), ans = 0;
                //创建map窗口,i为左区间,j为右区间,右边界移动
                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当前位置中更靠右的位置,这样是为了防止i向左移动
                        i = Math.max(map.get(s.charAt(j)), i);
                    }
                    //比对当前无重复字段长度和储存的长度,选最大值并替换
                    //j-i+1是因为此时i,j索引仍处于不重复的位置,j还没有向后移动,取的[i,j]长度
                    ans = Math.max(ans, j - i + 1);
    
                    // 将当前字符为key,下一个索引为value放入map中
                    // value为j+1是为了当出现重复字符时,i直接跳到上个相同字符的下一个位置,if中取值就不用+1了
                    map.put(s.charAt(j), j + 1);
                }
                return ans;
            }
        }
    
    
    
    
  • 解题思路(整型数组)

    LeetCode刷题之无重复字符的最长子串_第6张图片

  • 源码(整数数组)

    
    
        public class Solution {
           
            public int lengthOfLongestSubstring(String s) {
           
                int n = s.length(), ans = 0;
                int[] index = new int[128]; // current index of character
                // try to extend the range [i, j]
                for (int j = 0, i = 0; j < n; j++) {
           
                    i = Math.max(index[s.charAt(j)], i);
                    ans = Math.max(ans, j - i + 1);
                    index[s.charAt(j)] = j + 1;
                }
                return ans;
            }
        }
    
    
    
    
    
  • 复杂度分析
    LeetCode刷题之无重复字符的最长子串_第7张图片

其他

滑动窗口

  • 概念

    找到窗口中已存在的该字符所在位置,并将startIndex移动到该位置下一位
    LeetCode刷题之无重复字符的最长子串_第8张图片

你可能感兴趣的:(LeetCode,算法)