1.題目1:209. 長度最小的子陣列
1.1.解法1:暴力解法(已超時)
使用兩層迴圈,外層迴圈確定最小子陣列開始的位置(i),內層迴圈確定最小子陣列結束的位置(j)。在每次跳出內層迴圈時,sum應重置為0。
當找到的子陣列相加的和等於或大於目標值(target)時,算出此刻子陣列的長度(j - i + 1),並更新result的值。
最終在外層迴圈遍歷完所有元素時,對result值進行比較,如果result的值沒有發生變化,則不存在符合條件的子陣列,返回0。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size(), res = INT_MAX;
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += nums[j];
if (sum >= target) {
res = min(res, j - i + 1);
break;
}
}
}
return res == INT_MAX ? 0 : res;
}
};
● 時間複雜度:\(O(n^2)\)
● 空間複雜度:\(O(1)\)
1.2.解法2:滑動視窗
讓i最開始時指向陣列起始位置(視窗起始位置),當子陣列和大於目標值時,確定視窗的終止位置(j)。將視窗進行縮小,即將i所指位置向前推,相應sum減去i之前元素的值。
舉個例子:
nums = [1,1,1,1,100],target = 100。
當j指向100時,開始縮小視窗。i增大,sum減去1、1、1、1。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int res = INT_MAX;
int i = 0; // 滑動視窗起始位置
int sum = 0; // 滑動視窗數值之和
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// 每次更新i,比較子序列是否符合要求
while (sum >= target) {
res = min(res, j - i + 1); // 取子序列長度
sum -= nums[i++];
}
}
// 若res沒有被賦值,返回0,沒有符合條件的子序列
return res == INT_MAX ? 0 : res;
}
};
● 時間複雜度:\(O(n)\)
● 空間複雜度:\(O(1)\)
2.題目2:904.水果成籃
2.1.解法1:滑動視窗
這題與209的思考過程非常相似,但比較有意思的是使用了unordered_map,它與209中的sum使用方法是類似的。
簡述我的思考過程:
據題意,只能保留兩個型別的水果,並且需要連續收集儘可能多的水果數量。(即為只出現兩個數字且長度最大的連續子陣列)。
為了統計當前遍歷到的水果型別的數目,使用unordered_map來進行統計:<水果型別,該型別水果數目>,記為unordered_map<int, int>t。
我們設定一個指標j,一直遍歷陣列,另一個指標i,指向陣列的起始位置。
當j遍歷時,將水果加入t中,t[fruit[j]]++,fruit[j]為水果型別,t[fruit[j]]為當前統計的該型別水果的數目。
一旦當t.size()大於2時,我們需要將i所指水果減去,更新i所指位置,直至該視窗中僅包含兩種型別的水果,j才繼續向後遍歷。
res始終記錄視窗最大長度:res = max(res, j - i + 1)。
在本題中實現滑動視窗,主要確定如下三點:
● 視窗內是什麼?
● 如何移動視窗的起始位置?
● 如何移動視窗的結束位置?
視窗就是:只出現兩個數字且長度最大的連續子陣列。
視窗的起始位置如何移動:如果水果型別(unordered_map中元素)大於2,視窗就要向前移動,使得型別仍為2。
視窗的結束位置如何移動:視窗的結束位置就是遍歷陣列的指標,也就是for迴圈裡的索引。
class Solution {
public:
int totalFruit(vector<int>& fruits) {
int res = 0;
int i = 0;
unordered_map<int, int>t;
for (int j = 0; j < fruits.size(); j++) {
t[fruits[j]]++;
while (t.size() > 2) {
auto it = t.find(fruits[i]);
it->second--;
if (it->second == 0) t.erase(it);
i++;
}
res = max(res, j - i + 1);
}
return res;
}
};
● 時間複雜度:O(n)。
● 空間複雜度:O(1)。