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.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 }