leetcode 395 至少有K个重复字符的最长子串
作者:互联网
初始想到的方法是通过哈希的方式统计每个字母出现的频率,其中出现过的并且出现次数小于k的字符,就可以作为下一次递归的分界依据。而若是频率统计中所有出现的字符的次数都大于k,则认为这一子串是符合要求的,就返回当前子串长度至上一级中。贴代码
1 class Solution { 2 public: 3 int longestSubstring(string s, int k) 4 { 5 return dfs(s,0,s.length()-1,k); 6 } 7 int dfs(string& s,int l,int r,int k) 8 { 9 //cout<<l<<r<<endl; 10 if(r-l+1<k) 11 return 0; 12 int maxSize = 0; 13 vector<int> ch(27,0); 14 for(int i = l ; i <= r ; i++) 15 ch[s[i]-'a']++; 16 vector<int> pos; 17 for(int i = l; i <= r ; i++) 18 { 19 //如果该字符出现次数小于要求,则即为分界线 20 if(ch[s[i]-'a']<k && ch[s[i]-'a']>0) 21 pos.push_back(i); 22 } 23 if(!pos.size()) 24 return r-l+1; 25 //cout<<ch[0]<<endl; 26 pos.push_back(r+1); 27 int pos1 = -1; 28 for(int i = 0 ; i < pos.size() ; i++) 29 { 30 int pos2 = pos[i]; 31 int t = dfs(s,pos1+1,pos2-1,k); 32 if(t>maxSize) 33 maxSize = t; 34 pos1 = pos2; 35 } 36 return maxSize; 37 } 38 };
还有一种方法,就是滑动窗口,而滑动窗口的大小是窗口内部不同的字符种类。维护一个记录所有字符元素频率的数组,同时维护当前窗口中字符种类数与出现频率小于k的字符种类数。基本的循环为右边界向右移一位,将该字符对应的数组元素加一,同时调整chnum和lessk。若该数为新字符,则chnum++,lessK加加,若该数的频率到达K,则lessK--。然后判断当前窗口中字符种类数,若是大于目标种类数,则不断弹出左边界的元素,直到当前窗口中字符种类数等于目标种类数。并判断当前lessK是否为0,若是0,则代表当前窗口内的可以,则计算长度。贴代码
1 class Solution { 2 public: 3 int longestSubstring(string s, int k) 4 { 5 int res = 0; 6 int t = 1; 7 int n = s.length(); 8 for(t = 1 ; t <= 26 ; t++) 9 { 10 int chNum = 0; 11 int lessK = 0; 12 vector<int> countCh(26,0); 13 //t为字符种类 14 int l = 0; 15 int r = 0; 16 while(r<n) 17 { 18 countCh[s[r]-'a']++; 19 if(countCh[s[r]-'a'] == 1) 20 { 21 chNum++; 22 lessK++; 23 } 24 if(countCh[s[r]-'a'] == k) 25 lessK--; 26 //如果当前字符种类大于预设种类 27 while(chNum>t) 28 { 29 countCh[s[l]-'a']--; 30 if(countCh[s[l]-'a'] == 0) 31 { 32 chNum--; 33 lessK--; 34 } 35 if(countCh[s[l]-'a'] == k-1) 36 lessK++; 37 l++; 38 } 39 if(lessK == 0) 40 res = max(res,r-l+1); 41 r++; 42 } 43 } 44 return res; 45 } 46 };
标签:子串,字符,窗口,lessK,int,395,return,leetcode,种类 来源: https://www.cnblogs.com/zhaohhhh/p/15535281.html