3、Longest Substring Without Repeating Characters

题设

Given a string, find the length of the longest substring without repeating characters.
Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.
Given "bbbbb", the answer is "b", with the length of 1.
Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

要点

  • 双指针维护最长重复子串的位置
  • 动态规划

寻找字符串的最长子串,就是要维护一个区间[left , right),记录子串的左位置以及右位置,右位置可以由for循环参数替代。然后每次更新最大的子串长度即可。
刚开始使用暴力的解法,双重循环,不断更新[i,j)中i和j的位置,虽然能解,但是超时了。
超时了就到第一题给的提示,双重for循环超时,可以用hashMap来降低时间复杂度,所以可以根据String构造一个的hashMap。
在维护区间的过程中要注意,新的冲突发生的位置可能在区间左侧left的左边,这时候要维护left不往回退,即leftPosi = Math.max(leftPosi, map.get(s.charAt(i)) + 1)。

感觉应该也可以用动态规划来写。用boolean DP[i][j]来维护s[i,j]是否为非重复子串。对可能出现的子串的不同长度进行循环遍历判断,DP[i][j +1] = true的情况是DP[i][j] = true && s[i,j]不包含s[j + 1]。类似第5题回文串的思想。

    public static int lengthOfLongestSubstring(String s){
        int oriLen = s.length();
        int maxSubStringLen = 0;
        Map map = new HashMap(); // 用第一题的经验,把要遍历的数组存入hashMap,牺牲空间来节约时间到O(n)
        int leftPosi = 0; // 记录最长子串的左端位置
        for(int i = 0;i < oriLen;i++)
        {
            if(map.containsKey(s.charAt(i))) // 已经出现过,说明重复了
                leftPosi = Math.max(leftPosi, map.get(s.charAt(i)) + 1); // 出现新的重复,保证左指针不会回退!
            map.put(s.charAt(i), i);

            if(maxSubStringLen < i - leftPosi + 1) // 更新最长子串的长度
                maxSubStringLen = i - leftPosi + 1;
        }
        return maxSubStringLen;
    }

你可能感兴趣的:(3、Longest Substring Without Repeating Characters)