Template That Can Solve most Sub String Problem

the idea is inspired by Leetcode395 Longest substring with at least k duplicates
it’s a pretty difficult question.

following is the template for questions like this: we are given a string and need to find a substring of it which satify some restriction. as we can see in the template, a general way is to use a hashmap assisted with two pointers.

public int findSubstring(string s) {
    int[] map = new int[128];
    int counter;
    int begin = 0;
    int end = 0;
    int d; // the length of substring
    for() {
        //initialize map array here
    }
    while (end < s.size()) {
        if (map[s[end]] == ?) {
            map[s[end]]--;
            end++;
        }
        while (/counter condition/) {
            /* update d here if finding minimum*/

            //increase begin to make it invalid/valid again
                
            if(map[s[begin++]]++ ?){ /*modify counter here*/ }
        }
        /* update d here if finding maximum*/
    }
    return d;
}

I have write an article about LC076 minimum window substring, it general idea is exactly the same as previous, so just take a look at those template.
it’s pretty vague if you just look at the template, now, take leetcode 395 as example:
LC395. Longest Substring with At Least K Repeating Characters

class Solution {
    public int longestSubstring(String s, int k) {
        int d = Integer.MIN_VALUE;
        
        for (int numUniqueTarget = 1; numUniqueTarget <= 26; numUniqueTarget++) {
            d = Math.max(d, helper(s, k, numUniqueTarget));
            
        }
        return d;
    }
    
    private int helper(String s, int k, int numUniqueTarget) {
        int[] map = new int[128]; //why 128?because it contains every lowcase in the array so we don't have tp do map[s.charAt(i) - 'a'], instead, just use map[s.charAt(i)]
        int numUnique = 0; //count the number of unique in current substring
        int numNoLessThanK = 0; //count the number of unqiue char that has repeated >= K times
        int begin = 0; //begin pointer
        int end = 0; //end pointer
        int d = 0; //the length of "Substring with At Least K Repeating Characters" under current numUniqueTarget
        
        //the general idea of following loops: outter loop, which fixed end pointer, and the inner loop which moves begin pointer
        while (end < s.length()) {
            if (map[s.charAt(end)]++ == 0) numUnique++; // increment map[c] after this statement
            if (map[s.charAt(end++)] == k) numNoLessThanK++; // inc end after this statement
        
            while (numUnique > numUniqueTarget) {
                if (map[s.charAt(begin)]-- == k) numNoLessThanK--; // decrement map[c] after this statement
                if (map[s.charAt(begin++)] == 0) numUnique--; // inc begin after this statement
            }
        
        // if we found a string where the number of unique chars equals our target
        // and all those chars are repeated at least K times then update max
            if (numUnique == numUniqueTarget && numUnique == numNoLessThanK)
                d = Math.max(end - begin, d);
        }
        return d;
    }
}

LC3
Longest Substring Without Repeating Characters

 public int lengthOfLongestSubstring2(String s) {
    int[] map = new int[128];
    int start = 0, end = 0; //still two pinters, end used for exanding and start used for contraction
    int maxLen = 0, counter = 0; //

    while (end < s.length()) {
      final char c1 = s.charAt(end);
      if (map[c1] > 0) counter++; //counter used for keep track of the duplicate number in current substring(because if we already have char the same as c1 in map, then means we now meet a duplicate )
      map[c1]++; //update
      end++; //end move forward

      while (counter > 0) { //if we have a duplcate, then start to shrinking
        final char c2 = s.charAt(start); 
        if (map[c2] > 1) counter--; 
        map[c2]--; //update map
        start++; //update start
      }

      maxLen = Math.max(maxLen, end - start); //keeps track of maxLen
    }

    return maxLen;
  }

LC159
Longest Substring with At Most Two Distinct Characters

public int lengthOfLongestSubstringTwoDistinct(String s) {
    int[] map = new int[128];
    int start = 0, end = 0;
    int maxLen = 0, counter = 0;
    //counter used for count the number of distnct char in substring

    while (end < s.length()) {
      final char c1 = s.charAt(end);
      if (map[c1] == 0) counter++; //if we never meet before, means we got another unqiue char
      map[c1]++;
      end++;

      while (counter > 2) { //
        final char c2 = s.charAt(start);
        if (map[c2] == 1) counter--;
        map[c2]--;
        start++;
      }

      maxLen = Math.max(maxLen, end - start);
    }

    return maxLen;
  }

other problems that can be solved in this template:
LC209
LC424 bit of confused though

posted @ 2020-04-01 22:22  EvanMeetTheWorld  阅读(18)  评论(0)    收藏  举报