上海嘉定網(wǎng)站百度網(wǎng)訊科技有限公司官網(wǎng)
算法刷題
209. 長度最小的子數(shù)組-二分或者滑動窗口
給定一個含有 n
個正整數(shù)的數(shù)組和一個正整數(shù) target
。
找出該數(shù)組中滿足其總和大于等于 target
的長度最小的 連續(xù)子數(shù)組 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其長度**。**如果不存在符合條件的子數(shù)組,返回 0
思路
二分:
因為數(shù)據(jù)都是大于0的,因此數(shù)組的前綴和數(shù)組是單調(diào)增的,
我們遍歷每一個元素,二分去小最小的滿足s[r]-s[l-1]>=target
的位置即可。
時間復(fù)雜度為 O ( n l o g n ) O(nlogn) O(nlogn)
或者 :滑動窗口
維護(hù)一個變量sum
,記錄區(qū)間的和
兩個指針l,r
指向區(qū)間的尾巴和頭部,每次迭代,將nums[r]
加入到sum
中,
- 如果滿足
sum>=target
了,更新res
,并且指針l
右移,直到不滿足sum>=target
代碼
二分:
int minSubArrayLen(int target, vector<int>& nums) {int res=1e6;int n=nums.size();vector<int> s(n+10);for(int i=1;i<=n;i++) s[i]=s[i-1]+nums[i-1];for(int i=1;i<=n;i++){int l=i,r=n;while(l<r){int m=(l+r)>>1;if(s[m]-s[i-1]>=target) r=m;else l=m+1;}if(s[l]-s[i-1]>=target){res=min(res,l-i+1);}}if(res==1e6) res=0;return res;}
滑動窗口:
int minSubArrayLen(int target, vector<int>& nums) {int res=1e6;int l=0,r=0;int sum=0;int n=nums.size();for(;r<n;r++){sum+=nums[r];while(sum>=target) res=min(res,r-l+1),sum-=nums[l++];}if(res==1e6) res=0;return res;}
904. 水果成籃-滑動窗口
你正在探訪一家農(nóng)場,農(nóng)場從左到右種植了一排果樹。這些樹用一個整數(shù)數(shù)組 fruits
表示,其中 fruits[i]
是第 i
棵樹上的水果 種類 。
你想要盡可能多地收集水果。然而,農(nóng)場的主人設(shè)定了一些嚴(yán)格的規(guī)矩,你必須按照要求采摘水果:
- 你只有 兩個 籃子,并且每個籃子只能裝 單一類型 的水果。每個籃子能夠裝的水果總量沒有限制。
- 你可以選擇任意一棵樹開始采摘,你必須從 每棵 樹(包括開始采摘的樹)上 恰好摘一個水果 。采摘的水果應(yīng)當(dāng)符合籃子中的水果類型。每采摘一次,你將會向右移動到下一棵樹,并繼續(xù)采摘。
- 一旦你走到某棵樹前,但水果不符合籃子的水果類型,那么就必須停止采摘。
給你一個整數(shù)數(shù)組 fruits
,返回你可以收集的水果的 最大 數(shù)目。
思路
滑動窗口:
定義兩個指針:指向區(qū)間的開始和結(jié)尾
開一個哈希表來記錄區(qū)間內(nèi)每個元素出現(xiàn)的次數(shù),
如果哈希表的長度大于2了,那么就從左邊開始刪
注意當(dāng)哈希表內(nèi)沒有這個元素的時候,需要刪除key
代碼
int totalFruit(vector<int> &fruits) {int n = fruits.size();map<int, int> mp;int l = 0, res = 0;for (int r = 0; r < n; r++) {mp[fruits[r]]++;while (mp.size() > 2) {auto it= mp.find(fruits[l]);it->second--;if (mp[fruits[l]] == 0) mp.erase(it);l++;}res = max(res, r - l + 1);}return res;}
76. 最小覆蓋子串-滑動窗口
給你一個字符串 s
、一個字符串 t
。返回 s
中涵蓋 t
所有字符的最小子串。如果 s
中不存在涵蓋 t
所有字符的子串,則返回空字符串 ""
。
思路
滑動窗口:
開兩個哈希表,tt記錄t中每個字符出現(xiàn)的次數(shù),ss記錄窗口中每個字符出現(xiàn)的次數(shù)
遍歷字符串的右端點,每次去check是不是滿足tt的字符包含于ss的字符個數(shù)。
如果滿足,那么就可以不斷縮小左端點,更新答案
時間復(fù)雜度為 O ( 26 n ) O(26n) O(26n)
代碼
string minWindow(string s, string t) {int n = s.size();map<int, int> tt, ss;for (char c: t) tt[c]++;int len = 1e6, ansL = -1;int l = 0, r = -1;auto check = [&]() -> bool {for (auto [x, y]: tt) {if (ss[x] < y) return false;}return true;};while (r < n) {if (tt.find(s[++r]) != tt.end()) ss[s[r]]++;while (check() && l <= r) {if (r - l + 1 < len) {len = r - l + 1;ansL = l;}if (tt.find(s[l]) != tt.end()) ss[s[l]]--;l++;}}string res = "";if (ansL != -1) res = s.substr(ansL, len);return res;}
59. 螺旋矩陣 II-模擬
給你一個正整數(shù) n
,生成一個包含 1
到 n2
所有元素,且元素按順時針順序螺旋排列的 n x n
正方形矩陣 matrix
。
思路
按照題目模擬即可
代碼
vector<vector<int>> generateMatrix(int n) {int l=0,r=n-1,b=n-1,t=0;vector<vector<int>> res(n,vector<int>(n));int num=1,tar=n*n;while(num<=tar){for(int i=l;i<=r;i++) res[t][i]=num++;t++;for(int i=t;i<=b;i++) res[i][r]=num++;r--;for(int i=r;i>=l;i--) res[b][i]=num++;b--;for(int i=b;i>=t;i--) res[i][l]=num++;l++;}return res;}
54. 螺旋矩陣-模擬
給你一個 m
行 n
列的矩陣 matrix
,請按照 順時針螺旋順序 ,返回矩陣中的所有元素。
輸入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
輸出:[1,2,3,6,9,8,7,4,5]
輸入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
輸出:[1,2,3,4,8,12,11,10,9,5,6,7]
思路
模擬。
代碼
vector<int> spiralOrder(vector<vector<int>>& matrix) {int n=matrix.size(),m=matrix[0].size();vector<int> res;int l=0,r=m-1,t=0,b=n-1;int sum=n*m;while(sum){for(int i=l;i<=r;i++) res.push_back(matrix[t][i]),sum--;if(++t>b) break;for(int i=t;i<=b;i++) res.push_back(matrix[i][r]),sum--;if(--r<l) break;for(int i=r;i>=l;i--) res.push_back(matrix[b][i]),sum--;if(--b<t) break;for(int i=b;i>=t;i--) res.push_back(matrix[i][l]),sum--;if(++l>r) break;}return res;}
LCR 146. 螺旋遍歷二維數(shù)組-模擬
給定一個二維數(shù)組 array
,請返回「螺旋遍歷」該數(shù)組的結(jié)果。
螺旋遍歷:從左上角開始,按照 向右、向下、向左、向上 的順序 依次 提取元素,然后再進(jìn)入內(nèi)部一層重復(fù)相同的步驟,直到提取完所有元素。
示例 1:
輸入:array = [[1,2,3],[8,9,4],[7,6,5]]
輸出:[1,2,3,4,5,6,7,8,9]
示例 2:
輸入:array = [[1,2,3,4],[12,13,14,5],[11,16,15,6],[10,9,8,7]]
輸出:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
思路
模擬
代碼
vector<int> spiralArray(vector<vector<int>>& a) {vector<int> res; if(a.empty()) return res;int n=a.size(),m=a[0].size();int l=0,t=0,r=m-1,b=n-1;while(1){for(int i=l;i<=r;i++) res.push_back(a[t][i]);if(++t>b) break;for(int i=t;i<=b;i++) res.push_back(a[i][r]);if(--r<l) break;for(int i=r;i>=l;i--) res.push_back(a[b][i]);if(--b<t) break;for(int i=b;i>=t;i--) res.push_back(a[i][l]);if(++l>r) break;}return res;}