最多有两个不同字符的最长子串。题意是给一个字符串,请返回一个最长子串的长度。子串的要求是最多只有两个不同的字母。例子,
Example 1:
Input: "eceba" Output: 3 Explanation: tis "ece" which its length is 3.Example 2:
Input: "ccaabbb" Output: 5 Explanation: tis "aabbb" which its length is 5.
这题依然是用到sliding window的思想。给左右两个指针,并且创建一个hashmap,key是遍历到的字母,value是字母最后一次出现位置的index。扫描的时候,一开始只让右指针移动,把遍历到的字母和当前的坐标值加入hashmap。此时最大子串的长度就是左右指针的间距。当右指针遍历到第三个不同字母的时候,需要扫描hashmap,找到value(记为leftmost)最小的那个key并且删除这个键值对。此时左指针的位置是leftmost + 1。
时间O(n)
空间O(1) - 虽然有hashmap但是size很小,只有26个字母
1 /** 2 * @param {string} s 3 * @return {number} 4 */ 5 var lengthOfLongestSubstringTwoDistinct = function (s) { 6 let map = new Map(); 7 let left = 0; 8 let max = 0; 9 for (let right = 0; right < s.length; right++) { 10 map.set(s[right], right); 11 if (map.size > 2) { 12 let leftMostChar = null; 13 let leftMostIndex = Infinity; 14 for (let [char, index] of map) { 15 if (index < leftMostIndex) { 16 leftMostChar = char; 17 leftMostIndex = index; 18 } 19 } 20 map.delete(leftMostChar); 21 left = leftMostIndex + 1; 22 } 23 max = Math.max(max, right - left + 1); 24 } 25 return max; 26 };
另外一种模板写法。
Java实现
1 class Solution { 2 public int lengthOfLongestSubstringTwoDistinct(String s) { 3 // corner case 4 if (s == null || s.length() == 0) { 5 return 0; 6 } 7 8 // normal case 9 int[] map = new int[256]; 10 int start = 0; 11 int end = 0; 12 int maxLen = Integer.MIN_VALUE; 13 int counter = 0; 14 while (end < s.length()) { 15 char c1 = s.charAt(end); 16 if (map[c1] == 0) { 17 counter++; 18 } 19 map[c1]++; 20 end++; 21 while (counter > 2) { 22 char c2 = s.charAt(start); 23 if (map[c2] == 1) { 24 counter--; 25 } 26 map[c2]--; 27 start++; 28 } 29 maxLen = Math.max(maxLen, end - start); 30 } 31 return maxLen; 32 } 33 }
JavaScript实现
1 /** 2 * @param {string} s 3 * @return {number} 4 */ 5 var lengthOfLongestSubstringTwoDistinct = function(s) { 6 // corner case 7 if (s == null || s.length == 0) { 8 return 0; 9 } 10 11 // normal case 12 let start = 0; 13 let end = 0; 14 let maxLen = -Infinity; 15 let counter = 0; 16 let map = {}; 17 while (end < s.length) { 18 let c1 = s.charAt(end); 19 if (map[c1] == null || map[c1] <= 0) { 20 counter++; 21 } 22 map[c1] = map[c1] + 1 || 1; 23 end++; 24 while (counter > 2) { 25 let c2 = s.charAt(start); 26 if (map[c2] == 1) { 27 counter--; 28 } 29 map[c2]--; 30 start++; 31 } 32 maxLen = Math.max(maxLen, end - start); 33 } 34 return maxLen; 35 };