Leetcode4.17-4.23 4.17 滑动窗口 904.水果成篮 这个题目有点难理解,意思就是找至多包含两种元素的最长子串,返回其长度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution {public : int totalFruit (vector<int>& fruits ) { int i=0 ; int count=1 ; int result=1 ; vector<int> kind (fruits.size (),0 ); kind[fruits[i]]++; for (int j=1 ;j<fruits.size ();j++){ if (kind[fruits[j]]==0 ){ kind[fruits[j]]++; count++; } else { kind[fruits[j]]++; } while (count>2 ){ kind[fruits[i]]--; if (!kind[fruits[i]]){ count--; } i++; } result=result>(j-i+1 )?result :j-i+1 ; } return result; } };
滑动窗口加哈希表
改了两次bug 终于改对了 第一次是没注意已经放入HASH表中的元素遍历过程中对hash表的影响,即kind[fruits[j]]++;
还有就是我J从1开始,所以result开始时要设置为1;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution {public : int totalFruit (vector<int >& fruits) { int n = fruits.size (); unordered_map<int , int > cnt; int left = 0 , ans = 0 ; for (int right = 0 ; right < n; ++right) { ++cnt[fruits[right]]; while (cnt.size () > 2 ) { auto it = cnt.find (fruits[left]); --it->second; if (it->second == 0 ) { cnt.erase (it); } ++left; } ans = max (ans, right - left + 1 ); } return ans; } }; 作者:力扣官方题解 链接:https: 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我是用了一个向量起到了HASH的作用,官方直接用了相应的类,直接调用方法方便多了(unordered_map)
4.18 滑动算法 今天看一下labuladong的滑动窗口模板,解决一下这道困扰我很久的问题
unordered_map
就是哈希表(字典),相当于 Java 的 HashMap
,它的一个方法 count(key)
相当于 Java 的 containsKey(key)
可以判断键 key 是否存在。
76最小覆盖字串 模板框架
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 void slidingWindow (string s) { unordered_map<char , int > window; int left = 0 , right = 0 ; while (right < s.size ()) { char c = s[right]; winodw.add (c) right++; ... printf ("window: [%d, %d)\n" , left, right); while (left < right && window needs shrink) { char d = s[left]; winodw.remove (d) left++; ... } } }
窗口数据的更新
判断左侧窗口是否收缩的条件
滑动过程中题目所求的结果确认(最大或者最小)
(基本都用HASH表作为窗口数据的统计,然后写出判断条件)
这些点因题而异,但是基本逃不出上面的框架。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution {public : string minWindow (string s, string t) { int left=0 ,right=0 ; int count=0 ; int start=0 ,len=INT_MAX; unordered_map<char ,int > need,window; for (char c : t) need[c]++; while (right<s.size ()){ char c=s[right]; right++; if (need.count (c)){ window[c]++; if (window[c]==need[c]){ count++; } } while (count==need.size ()){ if (right-left<len){ len=right-left; start=left; } char d=s[left]; left++; if (need.count (d)){ if (need[d]==window[d]){ count--; } window[d]--; } } } return len==INT_MAX?"" :s.substr (start,len); }; };
4.19 滑动窗口 3 无重复字符的最长子串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution {public : int lengthOfLongestSubstring (string s) { int left=0 ,right=0 ; unordered_map<char ,int > window; int result=0 ; while (right<s.size ()){ char c=s[right]; right++; window[c]++; while (window[c]>1 ){ char d=s[left]; left++; window[d]--; } result=result>right-left?result:right-left; } return result; } };
438 找到字符串中所有字母异位词 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution {public : vector<int > findAnagrams (string s, string p) { int left=0 ,right=0 ; unordered_map<char ,int > need,window; for (char c:p) need[c]++; int count=0 ; vector<int > result; while (right<s.size ()){ char c=s[right]; right++; if (need.count (c)){ window[c]++; if (need[c]==window[c]){ count++; } } while (right-left>=p.size ()){ if (count==need.size ()) result.push_back (left); char d=s[left]; left++; if (need.count (d)){ if (window[d]==need[d]) { count--; } window[d]--; } } } return result; } };
两道题都套用了昨天的模板,太爽了,第一次做力扣这么舒服
4.20 151.反转字符串中的单词
这道题如果不用api,单纯的用C++的方式原地反转很复杂
先整个字符串反转,再分别反转字符串里面的单词
单词间可能不止一个空格,第一个单词和最后一个单词外面可能还有空格,要对字符串进行相应的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution {public : string reverseWords (string s) { reverse (s,0 ,s.size ()-1 ); int i=0 ,j=0 ; removespace (s); while (j<s.size ()){ if (s[j]==' ' ){ reverse (s,i,j-1 ); i=j+1 ; } j++; if (j==s.size ()-1 ){ reverse (s,i,j); } } return s; } void reverse (string& s,int start,int end) { while (start<end){ swap (s[start],s[end]); start++; end--; } } void removespace (string& s) { int slow=0 ,fast=0 ; while (s[fast]==' ' ){ fast++; } while (fast<s.size ()){ if (fast>0 &&s[fast]==' ' &&s[fast-1 ]==' ' ){ fast++; } else s[slow++]=s[fast++]; } if (slow>0 &&s[slow-1 ]==' ' ){ slow--; } s.resize (slow); } };
4.22 59螺旋矩阵 II 这个属于二维数组的花式遍历部分,直接上代码,最近忙项目,代码题解这能轻微带过,希望刷题量还能保持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution {public : vector<vector<int >> generateMatrix (int n) { vector<vector<int >> res (n,vector <int >(n,0 )); int up=0 ,low=n-1 ; int left=0 ,right=n-1 ; int num=1 ; while (num<=n*n) { if (up<=low){ for (int j=left;j<=right;j++){ res[up][j]=num++; } up++; } if (left<=right){ for (int i=up;i<=low;i++){ res[i][right]=num++; } right--; } if (up<=low){ for (int j=right;j>=left;j--){ res[low][j]=num++; } low--; } if (left<=right){ for (int i=low;i>=up;i--){ res[i][left]=num++; } left++; } } return res; } };