【string】hash table, two pointers, string
利用hash table, two pointers, string的题目。
1.求最长不重复子串的长度
hash table体现在一个数组,下标是字符串中元素的ASCII值,下标对应的元素代表该元素在字符串中出现的位置。
two pointers体现在用i一步步向前移去遍历字符串中的元素,作为不重复子串的末尾位置;用j指向不重复字符区间的首字符的位置。
1 /*************************** 2 @date 4.23 3 @description https://leetcode.com/problems/longest-substring-without-repeating-characters/ 4 Given a string, find the length of the longest substring without repeating characters. 5 For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. 6 For "bbbbb" the longest substring is "b", with the length of 1. 7 @tags: hash table, two pointers, string 8 用一个0~255的数组,数组下标是字符的ASCII值,数组里的内容初始化都为-1,表现未出现。 9 当其在字符串中出现,则赋值为当前字符在字符串中的下标; 10 变量i代表不重复字符区间末端的位置;j代表不重复字符区间第一个字符的位置; 11 当第一次出现重复字符时,该下标对应的值肯定是比j要大,此时将j赋值为该下标的后一位num[s[i]] + 1, i继续向前移,j<i 12 每次计算连续不重复字符的个数,并将其与max_len对比 13 ******************************/ 14 15 #include <iostream> 16 #include <string> 17 #include <memory.h> 18 using namespace std; 19 20 class Solution{ 21 public: 22 int lengthOfLongestSubstring(string s){ 23 int max_len = 0, len = 0; 24 int num[256]; 25 memset(num, -1, sizeof(num)); // 初始化为-1,表示没有出现过 26 for (int i = 0, j = 0; i < s.size(); ++i){ 27 if (num[s[i]] < j) 28 len = i - j + 1; // 统计连续不重复字符的个数 29 30 else // 如果第二次出现 31 j = num[s[i]] + 1; 32 if (max_len < len) 33 max_len = len; 34 num[s[i]] = i; 35 } 36 return max_len; 37 } 38 39 }; 40 41 42 int main(){ 43 Solution a; 44 cout << a.lengthOfLongestSubstring("abcdefgabcdefgh"); 45 }
2.子串变位词
hash table体现在一个数组,下标是字符串中字符的ASCII-'a',相当于0~25;下标对应的元素表示该字符出现的次数。
动态维护一个子串长度的窗口,a[i-lenb+1]~a[i]
1 /********************* 2 @date 4.22 3 @description 4 给定两个串a和b,问b是否是a的子串的变位词。(假设只含有全英的小写字母a~z) 5 例如输入a = hello, b = lel, lle, ello都是true,但是b = elo是false。 6 @tags: string, hash table, two pointers 7 8 ********************/ 9 10 #include <iostream> 11 #include <string> 12 13 using namespace std; 14 15 class Solution{ 16 public: 17 bool subStringAnagram(string a, string b){ 18 int nonZero = 0; 19 int num[26] = {0}; 20 int lena = a.size(); 21 int lenb = b.size(); 22 23 if (lena < lenb) 24 return; 25 26 for (int i = 0; i < lenb; i++) 27 if (++num[b[i] - 'a'] == 1) ++nonZero; // nonZero 有多少个字符非0次出现 28 29 30 for (int i = 0; i < lenb; ++i){ // 第一个窗口单独开,因为第一个窗口的第一个元素不能丢 31 int c = a[i] - 'a'; 32 --num[c]; // 此时的num[]变成了a,b对应元素出现的次数的差值 33 if (num[c] == 0) --nonZero; 34 else if(num[c] == 1) ++nonZero; 35 if (nonZero == 0) return true; 36 } 37 38 for(int i = lenb; i < lena; ++i){ 39 int c = a[i-lenb] - 'a'; 40 ++num[c]; // 扔掉a[i-lenb]; // 新窗口是a[i-lenb+1]...a[i] 41 if (num[c] == 1) ++nonZero; 42 else if(num[c] == 0) --nonZero; 43 c = a[i] - 'a'; // 旧窗口是a[i-lenb]....a[i-1] 44 --num[c]; // 加入a[i] 45 if (num[c] == 0) --nonZero; 46 else if(num[c] == -1) ++nonZero; 47 if (nonZero == 0) return true; 48 } 49 } 50 }; 51 52 53 int main(){ 54 Solution a; 55 cout << a.subStringAnagram("hello", "ell"); 56 }