文章目录
-
-
- 刷题目录
- 数组的理论知识
- [35. 搜索插入位置(二分)](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/)
-
刷题目录
数组的理论知识
二维数组不是连续地址空间,而是一个线性数组存放着 其它数组的首地址
35. 搜索插入位置(二分)
以后大家「只要看到面试题里给出的数组是有序数组,都可以想一想是否可以使用二分法。」
二分出来的一定是符合边界的,但不一定符合题意!要特判!
这一题解法1:二分边界是 >= target的值, 解法2:考虑 二分边界是 <= target的值
时间复杂度:O(logn)
解法1:二分边界是 >= target的值
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:二分边界是 <= target的值
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;
}
};