题目:给定一个字符串 s ,找出 至多 包含两个不同字符的最长子串 t ,并返回该子串的长度。
思路:使用hash表的优点在于,使用数组存储正在找的字符,用两个数组就很方便。统计个数也好,还是替代也好。其实看到这个题目,就知道有三种情况,第一种,表中只有两种字符以下的情况,只需要把新来的加入表中,或者把已存在的加入表中。第二种,表中有两个字符,但是新来的是这两个字符中的一个,此时只需要加个数。第三种,也是最复杂的,就是已经有两个了,但是新来的字符不同,因此,需要消掉第一个字符,第一个字符是哪个,有几个,怎么消除。就是这个题目的难点。
#define HASHNUM 128 //Z ASCII码值为127 int CheckHashNum(const int *hashArry) { int valueNum = 0; if (hashArry == NULL) { return false; } for (int i = 0; i < HASHNUM; i++) { if (hashArry[i] != 0) { valueNum++; } } return valueNum; } int Max(const int Num1, const int Num2) { if (Num1 >= Num2) { return Num1; } else { return Num2; } } int lengthOfLongestSubstringTwoDistinct(char * s){ if (s == NULL) { return false; } int maxNum = 0; int nowNum = 0; int start = 0; int cnt = 0; int strLen = strlen(s); int hash[HASHNUM] = {0}; for (int i = 0; i < strLen; i++) { cnt = CheckHashNum(hash); /*情况一,hash表只有一个种字符,处理完继续处理下一个,因此带contiue*/ if (cnt < 2) { hash[s[i]]++; nowNum ++; maxNum = Max(maxNum, nowNum); continue; } /*情况二,hash表有两个不同的字符,但是接下来的字符是其中之一,也加入hash中,处理完continue*/ if (cnt == 2) { if ((hash[s[i]] != 0)) { hash[s[i]]++; nowNum ++; maxNum = Max(maxNum, nowNum); continue; } } /*情况三,hash中有两种字符,但是接下来的字符不同于两种字符,因此去掉最头的字符,此处hash表的优势就体现出来了,因此没有用两个指针移动的形式,而是用hash表以数组的形式存储,用指针的形式的化,如果两个不同字符不是连续的,还要判断第一个字符最后一次出现在哪里*/ while (CheckHashNum(hash) >= 2 && start < strLen) { hash[s[start]]--; start++; nowNum--; } hash[s[i]]++; nowNum++; maxNum = Max(maxNum, nowNum); } return maxNum; }写代码途中的误区,这个continue,脑袋中一定要把逻辑理清,什么时候停,什么时候往下面跑
cnt = CheckHashNum(hash); /*情况一,hash表只有一个种字符,处理完继续处理下一个,因此带contiue*/ if (cnt < 2) { hash[s[i]]++; nowNum ++; maxNum = Max(maxNum, nowNum); continue; } /*情况二,hash表有两个不同的字符,但是接下来的字符是其中之一,也加入hash中,处理完continue*/ if (cnt == 2) { if ((hash[s[i]] != 0)) { hash[s[i]]++; nowNum ++; maxNum = Max(maxNum, nowNum); continue; } }