Longest substring without duplicate characters

1. Brute force method

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s==null){
            throw new NullPointerException();
        }
        if(s.isEmpty()){
            return 0;
        }
        if(s.length()==1){
            return 1;
        }

        String sbTemp;
        String sbMax = s.substring(0,1);
        int length = s.length();
        for (int i =0;i<length;i++){
            for (int j = i+1;j<length;j++){
                sbTemp = s.substring(i,j);
                boolean b = sbTemp.contains(String.valueOf(s.charAt(j)));
                if(b)
                    break;
                else
                    sbTemp = s.substring(i,j+1);
                sbMax = (sbTemp.length() > sbMax.length()) ? sbTemp : sbMax;
            }
        }
        return sbMax.length();
    }
}

2. Improve and use the containsKey method in hashmap

In this method, the containsKey method in HashMap is used to judge whether the String contains corresponding characters. In the above method, the contains method in the String class actually calls the indexOf method, and the bottom layer still traverses the character array; In the containsKey method in HashMap, the key is stored in the hash table. When searching, it is searched in the hash table. Its time complexity is: the best case is O(1), and the worst case is O(lgn)

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s==null){
            throw new NullPointerException();
        }
        if(s.isEmpty()){
            return 0;
        }
        if(s.length()==1){
            return 1;
        }

        String sbTemp;
        String sbMax = s.substring(0,1);
        int length = s.length();
        for (int i =0;i<length;i++){
            HashMap<Character, Integer> hashMap = new HashMap<>();
            for (int j = i;j<length;j++){
                sbTemp = s.substring(i,j+1);
                if(hashMap.containsKey(s.charAt(j)))
                    break;
                sbMax = (sbTemp.length() > sbMax.length()) ? sbTemp : sbMax;
                hashMap.put(s.charAt(j),j);
            }
        }
        return sbMax.length();
    }
}

3. Improve again and slide the window

Algorithm Introduction
Sliding window, as the name suggests, is a window with variable size, which slides forward in the same direction at the left and right ends (the right end is fixed and the left end slides; the left end is fixed and the right end slides).

It can be imagined as a queue, with one end in the push element and the other end in the pop element, as shown below:

Suppose there is an array [a b c d e f g h]
If a sliding window of size 3 slides on it, there are:
[a b c]
[b c d]
[c d e]
[d e f]
[e f g]
[f g h]
Scope of application
1. Usually a string or list
2. Generally, the minimum value (maximum length, minimum length, etc.) or subsequence is required
ps: the size of the sliding window can be adjusted according to the situation, that is, the size of the sliding window can change dynamically.
Algorithmic thought
1. In the sequence, use the left and right pointer skills in the double pointer, initialize left = right = 0, and call the index closed interval [left, right] as a window.
2. First, continuously increase the right pointer to expand the window [left, right] until the sequence in the window meets the requirements.
3. At this time, stop increasing right, and continue to increase the left pointer to narrow the window [left, right] until the sequence in the window no longer meets the requirements. At the same time, update the results every time before adding left.
4. Repeat steps 2 and 3 until right reaches the end of the sequence.
The idea is actually very simple: Step 2 is equivalent to looking for a feasible solution, and then step 3 is to optimize the feasible solution and finally find the optimal solution. The left and right pointers advance in turn, the window size increases and decreases, and the window continues to slide to the right.

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s==null)
            throw new NullPointerException();
        if(s.isEmpty())
            return 0;
        if(s.length()==1)
            return 1;
        //Left and right boundaries. After finding the largest, move the whole to the right
        int max = 0;
        int leftIndex = 0,rightIndex = 0;
        HashMap<Character, Integer> hashMap = new HashMap<>();
        hashMap.put(s.charAt(0),0);
        for (int i = 1;i<s.length();i++){
            if(hashMap.containsKey(s.charAt(i))){
                int temp = leftIndex;
                leftIndex=hashMap.get(s.charAt(i))+1;  //For the new leftIndex, you can directly choose to start with the subscript + 1 of the duplicate key because there are duplicates
                for(int j =temp;j<leftIndex;j++){  //Remove the key stored between left and i
                    hashMap.remove(s.charAt(j));
                }
                rightIndex++;
            }else {
                rightIndex++;
            }
            hashMap.put(s.charAt(i),i);
            max = Math.max((rightIndex-leftIndex+1),max);
        }
        return max;
    }
}

Code re Optimization:

class Solution {
       public int lengthOfLongestSubstring(String s) {
        // Record the last occurrence of the character
        int[] last = new int[128];
        for(int i = 0; i < 128; i++) {
            last[i] = -1;
        }
        int n = s.length();

        int res = 0;
        int start = 0; // Window start position
        for(int i = 0; i < n; i++) {
            int index = s.charAt(i);
            start = Math.max(start, last[index] + 1);
            res   = Math.max(res, i - start + 1);
            last[index] = i;
        }

        return res;
    }
}

The algorithm uses the prompt information given in the title, and the string is ASCII coded.

perhaps

class Solution {
    public int lengthOfLongestSubstring(String s) {
        // Record the last occurrence of the character
        int[] last = new int[128];
        int n = s.length();

        int res = 0;
        int start = 0; // Window start position
        for(int i = 0; i < n; i++) {
            int index = s.charAt(i);
            start = Math.max(start, last[index]);
            res   = Math.max(res, i - start + 1);
            last[index] = i+1; 
        }

        return res;
    }
}

Tags: Java leetcode

Posted on Thu, 02 Dec 2021 23:41:12 -0500 by Sako