Leetcode -- Day 17 & Day 18 & Day 19

substring

Question 1

Implement strStr()

Implement strStr().

Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

Below is my first direct solution, which looks complex in different case checking using if, else. 

 1 public int strStr(String haystack, String needle) {
 2         if (haystack == null || needle == null)
 3             return -1;
 4             
 5         int len1 = haystack.length();
 6         int len2 = needle.length();
 7         
 8         if (len2==0)
 9             return 0;
10             
11         if (len1 <= len2){
12             if (haystack.equals(needle)) return 0;
13             else return -1;
14         }
15             
16         for (int i = 0; i < len1; i ++){
17             if (haystack.charAt(i) == needle.charAt(0)){
18                 if (i+len2 > len1)
19                     return -1;
20                 String temp = haystack.substring(i, i+len2);
21                 if (needle.equals(temp))
22                     return i;
23             }
24         }
25         return -1;
26     }

Question 2

Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.
If we check it one by one character, it will exceed the time limit. So we must use a hashmap to remember the value and location each character has. And then if we find a repeat char, then we let the start index equals that char index + 1;
 1 public int lengthOfLongestSubstring(String s) {
 2         if (s == null || s.length() < 1)
 3             return 0;
 4         int start = 0;
 5         int res = 1;
 6         HashMap<Character, Integer> map = new HashMap<Character, Integer>();
 7         for (int i = 0; i < s.length(); i ++){
 8             char c = s.charAt(i);
 9             if (map.containsKey(c) && map.get(c) >= start){
10                 start = map.get(c) + 1;
11             }
12             else{
13                 res = Math.max(res, i-start+1);
14             }
15             map.put(c, i);
16         }
17         return res;
18     }

Question 3

Longest Palindromic Substring

Given a string S, find the longest palindromic substring inS. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

 Remember to deal with the same character repeat issue. So we will want two pointers. 

P2 move forward, if met same char, move one index further. And then start to compare p2+1 and p1-- is the same or not.

 1 public String longestPalindrome(String s) {
 2         if (s == null || s.length() <=1)
 3             return s;
 4         
 5         int start = 0;
 6         int longest = 0;
 7         for (int i = 0; i < s.length();){
 8             int p1 = i;
 9             int p2 = i;
10             while(p2<s.length()-1 && s.charAt(p2) == s.charAt(p2+1)){
11                 p2 ++;
12             }
13             i = p2 + 1;
14             while(p1>0 && p2<s.length()-1 && s.charAt(p1-1) == s.charAt(p2+1)){
15                p1--;
16                p2++;
17             }
18             int len = p2 - p1 + 1;
19             if (len > longest){
20                 start = p1;
21                 longest = len;
22             }
23         }
24         return s.substring(start, start + longest);
25

Question 4

Substring with Concatenation of All Words

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in wordsexactly once and without any intervening characters.

For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

We need to use two hashmaps here. One for record all word phrase in the String[] words. Another one for record the second loop for the string's substring to compare whether is it in the first hashmap and whether it appear the same times as it occurs in the first map.

String temp = s.substring(i+j*wordLen,i+(j+1)*wordLen);

Note: for the above one, every time we get a substring with len = wordLen(i.e. "foo" = 3)


 1 public List<Integer> findSubstring(String s, String[] words) {
 2         List<Integer> res = new ArrayList<Integer>();
 3         HashMap<String, Integer> map = new HashMap<String, Integer>();
 4         int wordNum = words.length;
 5         int wordLen = words[0].length();
 6         
 7         if (wordNum*wordLen > s.length())
 8             return res;
 9             
10         for (int i = 0; i < words.length; i ++){
11             if (!map.containsKey(words[i]))
12                 map.put(words[i], 1);
13             else
14                 map.put(words[i], map.get(words[i])+1);
15         }
16         
17         for (int i = 0; i <= s.length() - wordLen*wordNum; i++){
18             HashMap<String, Integer> found = new HashMap<String, Integer>();
19             int j;
20             for (j = 0; j < wordNum; j ++){
21                 String temp = s.substring(i+j*wordLen,i+(j+1)*wordLen);
22                 if (!map.containsKey(temp)) break;
23                 if (!found.containsKey(temp)) 
24                     found.put(temp, 1);
25                 else
26                     found.put(temp, found.get(temp)+1);
27                 if (found.get(temp)>map.get(temp))
28                     break;
29             }
30             if (j == wordNum)
31                 res.add(i);
32         }
33         return res;
34

Question 5

Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = "ADOBECODEBANC"
T = "ABC"

Minimum window is "BANC".

Note:
If there is no such window in S that covers all characters in T, return the emtpy string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

We use two int[256] instead of hashset here. Very complex. Still need foFind and found this two array.

And every two while loop, we can get a new window size, we need to check whether it is the minimum one.

 1 public String minWindow(String s, String t) {
 2         String res = "";
 3         if (s.length() < t.length())
 4             return res;
 5             
 6         int[] toFind = new int[256];
 7         int[] found = new int[256];
 8         
 9         for (int i = 0; i < t.length(); i++){
10             char c = t.charAt(i);
11             toFind[c] ++;
12         }
13         
14         int start = 0; 
15         int end = 0;
16         int need = t.length();
17         int minWindow = Integer.MAX_VALUE;
18         
19         while(end < s.length()){
20             while (need > 0 && end < s.length()){
21                 char c = s.charAt(end);
22                 if (toFind[c] > 0){
23                     if (found[c] < toFind[c] )
24                         need --;
25                     found[c] ++;
26                 }
27                 end ++;
28             }
29             
30             while (need == 0){
31                 if (end - start < minWindow){
32                     res = s.substring(start, end);
33                     minWindow = end-start;
34                 }
35                 char c = s.charAt(start);
36                 if (toFind[c] > 0){
37                     found[c] --;
38                     if (found[c] < toFind[c])
39                         need ++;
40                 }
41                 start ++;
42             }
43         }
44         
45         return res;
46     }

Question 6

Longest Substring with At Most Two Distinct Characters

Given a string, find the length of the longest substring T that contains at most 2 distinct characters.
For example,Given s = “eceba”,
T is "ece" which its length is 3.

I use a hashmap to record the two distinct characters. And then loop through the string. If the hashmap found.size() == 2 && the hashmap.containsKey(next char) == false, means we already get two distinct chars and cannot put in the third one, as it is another distinct char. So we need to stop here and count the number of chars of this substring. What we need to remember is that the size of the hashmap should always be 2, so, we will check each time from the start =0 to start = i. If the s.charAt(start) in the map, then we need to substract 1. Until all the map.size() is not 2, we will stop and count the Math.max(i-start+1,max).

 1 public class Solution {  
 2     public int lengthOfLongestSubstringTwoDistinct(String s) {  
 3         //input check  
 4         if(s== null || s.length()==0) return 0;  
 5         Map<Character, Integer> map = new HashMap<Character, Integer>();  
 6         int start = 0;  
 7         int max = 0;  
 8         for(int i=0; i<s.length(); i++) {  
 9             char c = s.charAt(i);  
10             if(map.containsKey(c)) {  
11                 map.put( c,   map.get(c) + 1 );  
12             } else if(map.size() < 2) {  
13                 map.put(c, 1);  
14             } else {//map does not contain current character, and map size>=2  
15                 //map size == 2, to satisfy at most 2 distinct character
16                 //i - current character
17                 while((map.size()==2) && start<i) {  
18                     char temp = s.charAt(start);  
19                     int x = map.get(temp);  
20                     --x;  
21                     if(x==0) map.remove(s.charAt(start));  
22                     else map.put(s.charAt(start), x);  
23                     ++start;  
24                 }  
25                 map.put(c,1);  
26             }  
27             max = Math.max(max, i-start+1); //i-start+1: current length, max: previous max length 
28         }  
29         return max;  
30     }  
31 }  

 

原文地址:https://www.cnblogs.com/timoBlog/p/4674957.html