記事のディレクトリ
-
-
- 質問リスト
- 配列の理論的知識
- [35.挿入位置の検索(2ポイント)](https://leetcode-cn.com/problems/search-insert-position/)
- [27.要素の削除(デュアルポインター)](https://leetcode-cn.com/problems/remove-element/)
- [209.最小長のサブアレイ(スライディングウィンドウ)](https://leetcode-cn.com/problems/minimum-size-subarray-sum/)
- [59.スパイラルマトリックスII(シミュレーション)](https://leetcode-cn.com/problems/spiral-matrix-ii/)
-
質問リスト
配列の理論的知識
2次元配列は、連続したアドレス空間ではなく、他の配列の最初のアドレスを格納する線形配列です。
35.挿入位置の検索(2点)
以后大家「只要看到面试题里给出的数组是有序数组,都可以想一想是否可以使用二分法。」
二分出来的一定是符合边界的,但不一定符合题意!要特判!
这一题解法1:二分边界是 >= target的值, 解法2:考虑 二分边界是 <= target的值
时间复杂度:O(logn)
解決策1:二分境界は値> =ターゲットです
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
// 已排好序,二分查找
int l = 0,r = nums.size() ; // 预留多一个位置,防止插在最后
while(l < r)
{
int mid = l + r >> 1;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
return r;
}
};
解決策2:二分境界は<=ターゲットの値です
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while(l < r)
{
int mid = l + r + 1>> 1;
if(nums[mid] <= target) l = mid;
else r = mid - 1;
}
if(target <= nums[0]) return 0; // 特判
if(nums[r] != target) return r + 1;
return r;
}
};
27.要素を削除します(ダブルポインター)
双指针,可从O(n ^ 2)降到O(n)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
// 快慢指针
// 时间复杂度:O(n)
// 空间复杂度:O(1)
int slow = 0;
for(int fast = 0;fast < nums.size(); fast ++)
{
if(val != nums[fast]) nums[slow ++ ] = nums[fast];
}
return slow;
}
};
209.最小のサブアレイ(スライディングウィンドウ)
滑动窗口:利用单调性优化,可从O(n ^ 2) 降到 O(n)
注意边界:没有符合条件的子数组
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
// 时间复杂度O(n)
int len = nums.size() + 1;
int sum = 0;
for(int i = 0, j = 0;i < nums.size();i ++ )
{
sum += nums[i];
while(sum >= s)
{
len = min(len, i - j + 1); // 长度是i - j + 1;
sum -= nums[j ++ ];
}
}
if(len == nums.size() + 1) return 0; // 特判,表示没有符合条件的连续子数组
return len;
}
};
59.スパイラルマトリックスII(アナログ)
定义四个偏移量,利用方向矢量来模拟
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n)); // 初始化
vector<vector<bool>> st(n,vector<bool>(n,false)); // 是否访问过
int dx[4] = {
-1,0,1,0}, dy[4] = {
0,1,0,-1}; // 上右下左
int x = 0,y = 0; // 初始坐标
int d = 1; // 初始方位
for(int i = 1;i <= n * n ;i ++ )
{
res[x][y] = i;
st[x][y] = true;
int tx = x + dx[d], ty = y + dy[d];
if(tx < 0 || tx >= n || ty < 0 || ty >= n || st[tx][ty]) // 出界或者已访问,就转向
{
d = (d + 1) % 4;
tx = x + dx[d], ty = y + dy[d]; // 转向,重新计算坐标
}
x = tx, y = ty;
}
return res;
}
};