Brush title LeetCode - No repetition longest substring of characters (medium)

 Subject description:

Given a string, you find out which does not contain a repeated character  longest substring  length.

 Example 1:

Enter: "abcabcbb"

Output: 3

Explanation: Because the longest non-repeating sub-character string is "abc",所以其of length 3.

 Example 2:

Enter: "bbbbb"

Output: 1

Explanation: Because the longest non-repetitive characters strings are child "b", so its length is 1.

Example 3:

Input: "pwwkew"
Output: 3
Explanation: Because the longest sub-string is repeated characters without "wke", so its length is 3.
    Please note that your answer must be a substring of length, "pwke" is a sub-sequence, not a substring.

    Substring: sequences of any consecutive string of characters called a sub-string of the string

Method One: Violence Act

After the title update due to time constraints, there will TLE (time-out).

 

Thinking

Check all one by one substring, to see if it does not contain repeating characters.

 

key point

Suppose we have a function boolean allUnique (String substring), if the child characters in the string is unique, it returns true, otherwise returns false. We can iterate to all possible substring given string s and call the function allUnique.

If it turns out the return value is true, we will update the character substring no duplicate answers maximum length.

Now let's fill in the missing parts:

1. In order to enumerate all substring of the given string, we need to enumerate them starting and ending index.

2. To check if there is a string of repeated characters, we can use the collection. We traverse all the characters in a string, one by one and put them in the set.

Before placing a character, we check whether the collection already contains it. If it does, we will return false. After the end of the cycle, we return true.

 

Code

class Solution {
     public  int lengthOfLongestSubstring (String S) {
         // string length 
        int n-= s.length ();
         // is the length of the longest substring 
        int ANS = 0 ;
         for ( int I = 0; I <n-; ++ I ) {
             for ( int J = I +. 1; J <= n-; J ++ ) {
                 IF (allUnique (S, I, J)) {
                     // update value ans, whichever is the maximum 
                    ans = Math.max (ans, j - I); 
                } 
            } 
        } 
        returnANS; 
    } 

    / ** 
     * no repeat request longest character longest substring 
     * 
     * @param S string length 
     * @param Start start position of the current string 
     * @param End the current end position of the string 
     * @return ture or false, decide whether or not to enter the above if loop
      * / 
    public  Boolean allUnique (String S, int Start, int End) { 
        the Set <Character> SET = new new HashSet <> ();
         for ( int I = Start; I <End; I ++ ) {
             // i-th character in the string content
            Ch = Character s.charAt (I);
             // the Set contains the string set ch 
            IF (set.contains (ch)) {
                 return  to false ; 
            } 
            // If not, go out into the collection set ch Add string 
            set. the Add (CH); 
        } 
        return  to true ; 
    } 
}

 

the complexity: 

Time complexity: O (n- . 3 )

 

Method two: sliding window

What is the sliding window?

Is actually a queue, such as examples of abcabcbb, enter the queue (window) as abc meet the subject requirements, when re-entering a, queue becomes abca, this time does not meet the requirements. So, we want to move the queue!
How do I move?
We just put the elements left out of the queue on the line, until meeting questions asked! Has maintained such a queue, the queue to find the longest length of time appears, find the solution!

Of course, the size of the sliding window may be fixed or may be dynamic

 

Thinking

HashSet as by using a sliding window, we can use the  O (. 1) O ( . 1 ) checks whether the time to complete the current sub-character string.

 

回到我们的问题,我们使用HashSet将字符存储在当前窗口[i,,j)(最初=i)中。然后我们向右侧滑动索引j,如果它不在HashSet中,我们会继续滑动。直到si]已经存在于HashSet中。此时,我们找到的没有重复字符的最长子字符串将会以索引i开头。如果我们对所有的i这样做,就可以得到答案。

 

代码

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        //字符串长度
        int n = s.length();
        Set<Character> set = new HashSet<>();
        //定义ans为最长子串的长度,如果j的值没有在set出现过end++,知道出现start++,滑动窗口
        int ans = 0, start = 0, end = 0;
        //如果start和end<n就一直遍历,直到start和end都小于n
        while (start < n && end < n) {
            //判断Set集合是否包含end下标对应的字符串
            if (!set.contains(s.charAt(end))){
                //如果set里没有,则把j下标对应的字符串存进set集合, end执行完本句后+1
                set.add(s.charAt(end++));
                //因为end++,所有滑动窗口向后移动,并更新ans的值
                ans = Math.max(ans, end - start);
            }
            else {
                //移除Set集合start下标对应的字符串,start++,最后全部移除
                set.remove(s.charAt(start++));
            }
        }
        return ans;
    }
}

 

复杂度

时间复杂度:O(2n)=O(n),在最糟糕的情况下,每个字符将被i和j访问两次。

空间复杂度:O(min(m,n)),与之前的方法相同。滑动窗口法需要O(k)的空间,其中k表示Set的大小。而Set的大小取决于字符串n的大小以及字符集/字母m的大小。

 

方法三:优化的滑动窗口

上述的方法最多需要执行2n个步骤。事实上,它可以被进一步优化为仅需要n个步骤。我们可以定义字符到索引的映射,而不是使用集合来判断一个字符是否存在。当我们找到重复的字符时,我们可以立即跳过该窗口。

也就是说,如果s[j]在[i,j)范围内有与j重复的字符,我们不需要逐渐增加i。我们可以直接跳过[i,j门范围内的所有元素,并将i变为j+1。

 

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length(), ans = 0;
        //创建map窗口
        Map<Character, Integer> map = new HashMap<>();
        //定义不重复子串的开始位置为 start,结束位置为 end
        for (int end = 0, start = 0; end < n; end++) {
            if (map.containsKey(s.charAt(end))) {
                // 随着 end 不断遍历向后,会遇到与 [start, end] 区间内字符相同的情况,
                // map.get(s.charAt(end)此时将字符作为 key 值,获取其 value 值,
                // 此时 [start, end] 区间内不存在重复字符。
                // 修改start值为之前重复字符位置之后的位置
// start更新时进行比较是因为map里key放的是所有遍历过的字符,而不仅仅是窗口里的字符。
          // 所以现在的字符如果跟窗口外的字符(也就是以前的字符)重复了,start应该保持原样
start = Math.max(map.get(s.charAt(end)), start); } //比对当前无重复字段长度和储存的长度,选最大值并替换 //end-start+1是因为此时i,end索引仍处于不重复的位置,end还没有向后移动,取的[start,end]长度,+1因为索引从1开始 //无论是否更新 start,都会更新其 map 数据结构和结果 ans。 ans = Math.max(ans, end - start + 1); // 将当前字符为key,value 值为字符位置 +1 // 加 1 表示从字符位置后一个才开始不重复,不然就把最后一个数给替换了 map.put(s.charAt(end), end + 1); } return ans; } }

 

 

复杂度

时间复杂度:O(n),索引j将会迭代n次。

空间复杂度(HashMap):O(min(m,n)),与之前的方法相同。

空间复杂度(Table):O(m),m是字符集的大小。

 画解

 

 

 

 

 

 

 

 

Guess you like

Origin www.cnblogs.com/xiaozhongfeixiang/p/12016590.html