模拟数组
54. 螺旋矩阵
思路:
对于在matrix的任意坐标(x, y):
向右:(x, y) + (0, 1)
向下:(x, y) + (1, 0)
向左:(x, y) + (0, -1)
向上:(x, y) + (-1, 0)
此螺旋矩阵的产生顺序 就是 往右,撞墙,往下,撞墙,往左,撞墙,往上的循环。
通过将粗体的和非粗体的归为俩类,得到以下数组:
int d_1[4] = {0, 1, 0, -1};
int d_2[4] = {1, 0, -1, 0};
可以发现:
向右:(x, y) + (d_1[0],d_2[0])
向下:(x, y) + (d_1[1],d_2[1])
向左:(x, y) + (d_1[2],d_2[2])
向上:(x, y) + (d_1[3],d_2[3])
同步遍历这俩个数组刚好可以改变方向。
实现难点:
难点一:如何让遍历数组的index 的值改变顺序为 0 -> 1 -> 2 -> 3 -> 0 -> 1 (这样才符合题目中右,下,左,上,右...的顺序)
使用mod d = (d + 1) % 4
难点二:什么时候换方向
- index 越界
- 遇到走过的元素,比如上图例子中 4 再往上走就是1,然而 1已经走过,所以换方向到右边
#include <iostream>
#include <vector>
class Solution {
public:
vector<int> result;
int d_1[4] = {0, 1, 0, -1};
int d_2[4] = {1, 0, -1, 0};
int x = 0, y = 0, d = 0, k = 0;
std::vector<int> spiralOrder(std::vector<std::vector<int>>& matrix) {
int m = matrix.size(); // row
int n = matrix[0].size(); // col
result.resize(m * n);
for (int i = 1; i <= m * n; i++) {
result[k++] = matrix[x][y];
std::cout << "turn: " << i << ", value: " << matrix[x][y] << endl;
matrix[x][y] = true ;
x = x + d_1[d];
y = y + d_2[d];
cout << "d: " << d << endl;
printf("new_x : %d, new_y: %d \n", x, y);
//越界的时候需要换方向,走过的地方不能再走也要换方向
if (x < 0 || y < 0 || x >= m || y >= n || matrix[x][y] == true) {
cout << "collison: yes " << endl;
x = x - d_1[d];
y = y - d_2[d];
d = (d + 1) % 4;
cout << "d " << d << endl;
x = x + d_1[d];
y = y + d_2[d];
}
}
return result;
}
};
滑动窗口:209. 长度最小的子数组
题目中提到连续的时候可以考虑用滑动窗口,有时窗口有大小
基本模板:
for ( ){
while(conditon) {
收缩窗口
}
}
class Solution {
public:
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
int minSubArrayLen(int target, vector<int>& nums) {
int hh = 0, tt = -1;
int sum = 0;
int min_v = INF;
int q[N];
for(int i = 0; i < nums.size(); i ++){
q[++tt] = i;
sum += nums[i];
// printf("turn: %d, %d, %d\n", i, nums[q[tt]], nums[q[hh]]);
while(tt >= hh && sum >= target){
//因为要最短,所以要尽量多收缩,这样可以随后加入较少新的元素
min_v = min(tt - hh + 1, min_v);
// printf("turn: %d, %d, %d\, min:%d\n", i, nums[q[tt]], nums[q[hh]], min_v);
sum = sum - nums[q[hh++]];
// cout << sum << endl;
}
}
return min_v = min_v != INF?min_v:0;
}
};
相向双指针:977. 有序数组的平方
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result(nums.size(), 0); //记得resize
int l = 0, r = nums.size() -1;
int k = nums.size() - 1;
while(l <= r){
if(abs(nums[l]) >= abs(nums[r])){
result[k--] = nums[l] * nums[l] ;
l ++;
// printf("%d is larger \n", nums[l]);
}
else{
result[k--] = nums[r] * nums[r];
// printf("%d is larger \n", nums[r]);
r --;
}
}
return result;
}
};
思路:
nums = [-4,-1,0,3,10]
感觉跟merge_sort的merge的很相似,l++ 和 r-- 都是遍历递减顺序,比较俩个递减顺序哪个更大,更大的就放在结果数组尾部
注意:
边界条件 一定是 <=, 因为 达到 l == r 之前都一步不论是r--向左走还是l++向右走,指针 l 和 r 在此之后都会相遇指向最后一个没有被放入的元素,只有 <=才能把这最后一个元素放入