代码随想录Day2 | 54. 螺旋矩阵(螺旋矩阵的小技巧),209. 长度最小的子数组,977. 有序数组的平方

本文介绍了如何在C++中使用螺旋矩阵的思路,包括通过定义两个向量d_1和d_2控制移动方向,难点在于调整遍历数组的索引顺序和判断何时改变方向。同时提及了滑动窗口和相向双指针算法在处理其他问题中的应用。
摘要由CSDN通过智能技术生成


模拟数组

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 在此之后都会相遇指向最后一个没有被放入的元素,只有 <=才能把这最后一个元素放入

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值