209.長度最小的子陣列https://leetcode.cn/problems/minimum-size-subarray-sum/: 給定一個含有n
個正整數的陣列和一個正整數target
。找出該陣列中滿足其總和大於等於target
的長度最小的子陣列[nums_l, nums_{l+1}, ..., nums_{r-1}, nums_r]
,並返回其長度。如果不存在符合條件的子陣列,返回0
。
(1)暴力求解法:利用兩個迴圈,分別遍歷子列的起始位置和終止位置;若檢查到和>= target
的子列,將其長度記為len;實時更新滿足條件的最短子列長s。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0, len = 0, s = nums.size()+10;
for (int i = 0; i < nums.size(); i++){
sum = 0;
for (int j = i; j <nums.size(); j++){
sum += nums[j];
if (sum >= target) {
len = j-i+1;
break;
}
else len = nums.size()+10;
}
if (s > len) s = len;
}
return s == nums.size() + 10 ? 0 : s;
}
};
時間複雜度:O(n^2)
,這導致當n
很大時超出時間限制;
空間複雜度:O(1)
。
(2)移動視窗解法:利用一個for迴圈遍歷視窗終止位置,以其和sum
是否大於target
作為元素是否在視窗中的依據。若sum
小於target
,向後移動視窗終止位置;若sum
大於target
,向後移動視窗起始位置。注意移動時和sum
的變化;並實時記錄和比較子列長度。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0, sublenth = 0, result = INT32_MAX;
int i = 0; //star index
for (int j = 0; j < nums.size(); j++){
sum += nums[j];
while(sum >= target){
sublenth = j - i + 1;
result = result < sublenth ? result : sublenth;
sum -= nums[i++]; // 這裡體現出滑動視窗的精髓之處,不斷變更i
continue;
}
}
return result == INT32_MAX ? 0 : result;
}
};
空間複雜度:O(n)
;
時間複雜度:O(1)
。
(3)解題困難:①不能準確判斷移動視窗的起始位置i和終止位置j的設定;②嘗試先固定子陣列長度,再找滿足和條件的子陣列,最終還是要用兩個迴圈。
59.螺旋矩陣https://leetcode.cn/problems/spiral-matrix-ii/: 給你一個正整數n
,生成一個包含1
到n^2
所有元素,且元素按順時針順序螺旋排列的n x n
正方形矩陣matrix
。
(1)自我思路:n
為奇數時有中心,為偶數時只有外圈;一圈四邊,每邊的元素數目只計算左閉右開區間內的元素。
(2)迴圈求解:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
std::vector<std::vector<int>> arr(n, std::vector<int>(n,0));
int loop = n / 2; //記錄要填充圈數,n為奇數時還需要單獨處理中間位置
int startx = 0, starty = 0; // 定義每迴圈一個圈的起始位置
int mid = n/2;//記錄中間位置
int offset = 1;
int count = 1;
int i, j;
while (loop--){
i = startx; j = starty;
for (j; j < n - offset; j++){ //j從0變到n-offset,n-offset未進入迴圈
arr[i][j] = count++;
}
for (i; i < n - offset; i++) {//j從0變到n-1
arr[i][j] = count++;
}
for (; j > startx; j--){ //j從n-offset 變到startx
rr[i][j] = count++;
}
for (; i > starty; i--){ //i從n-offset 變到starty
arr[i][j] = count++;
}
// 第二圈開始的時候,起始位置要各自加1
startx++;
starty++;
// offset 控制每一圈裡每一條邊遍歷的長度
offset += 1;
}
if (n % 2) arr[mid][mid] = n*n;
return arr;
}
};
時間複雜度:O(n^2)
;
空間複雜度:O(1)
。
(3)主要困難:誤用行列乘積給元素賦值;區間端點i與j的設定;
(4)收穫:自增運算子有共同效果和細微區別。① 字尾自增:i++ 會先返回 i 的當前值,然後 i 的值增加1。② 字首自增:++i 會先將 i 的值增加1,然後返回 i 的新值。例如
int i = 1;
int a = i++; // a = 1, i = 2
int b = ++i; // i = 3, b = 3