Leetcode 159 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.
Solution:
1. use Hashtable
hashtable来存字母和index 的pair。即时更新hashtable。
public int LengthOfLongestSubstringTwoDistinct(string s) { Dictionary<char,int> hashtable = new Dictionary<char,int>(); int max = 0; int sum =0; for(int i =0;i< s.Length;i++) { if(hashtable.ContainsKey(s[i])) { sum++; hashtable[s[i]] = i; } else if(hashtable.Count()<2) { sum++; hashtable.Add(s[i],i); } else//need to exchange a charactersitic { var a = new List<char>(); var b = new List<int>(); foreach (var pair in hashtable) { a.Add(pair.Key); b.Add(pair.Value); } if(b[0]>b[1]) { sum = i-b[1]; hashtable.Remove(a[1]); } else { sum = i-b[0]; hashtable.Remove(a[0]); } hashtable.Add(s[i],i); } max = Math.Max(max,sum); } return max; }
The hashtable Method is easy to extend to K Distince Characters. But we need to do a little change becasue we need to remove the element from Dictionary by value, so we can use Linq. Here is the changed code:
public int LengthOfLongestSubstringTwoDistinct(string s) { Dictionary<char,int> hashtable = new Dictionary<char,int>(); int max = 0; int sum =0; for(int i =0;i< s.Length;i++) { if(hashtable.ContainsKey(s[i])) { sum++; hashtable[s[i]] = i; } else if(hashtable.Count()<2) { sum++; hashtable.Add(s[i],i); } else//need to exchange a charactersitic { int leftMost = Int32.MaxValue; foreach (var pair in hashtable) { leftMost = Math.Min(leftMost, pair.Value); } sum = i-leftMost; var needRemove = hashtable.First(x => x.Value ==leftMost ); hashtable.Remove(needRemove.Key); hashtable.Add(s[i],i); } max = Math.Max(max,sum); } return max; }
2. 2 pointer & sliding window
从网上看到的用sliding window来track 两个字母中左边的最右位, j用来track左边字母的最右位,如果出现字母与其左边临近字母不同,再检查是否是之前左边的字母,如果是,j赋新值;如果不是,则计算最大距离并用i代表substring的最左端。
public int LengthOfLongestSubstringTwoDistinct(string s) { int i = 0, j = -1; int maxLen = 0; for (int k = 1; k < s.Length; k++) { if (s[k] == s[k-1]) continue; if (j > -1 && s[k] != s[j]) { maxLen = Math.Max(maxLen, k - i); i = j + 1; } j = k - 1; } return maxLen > (s.Length - i) ? maxLen : s.Length - i; }