代码随想录day2

代码随想录day2的数组题目

文章参考的代码随想录的网址:代码随想录的数组章节的参考地址

977.有序数组的平方:

有序数组的平方

刚看题的思路 :

 暴力解决,先平方出来,然后用sort函数来排序,但这种算法的时间复杂度为  O(n + nlogn)
class Solution {
public:
    vector<int> sortedSquares(vector<int>& A) {
        for (int i = 0; i < A.size(); i++) { //遍历容器A的元素
            A[i] *= A[i];
        }
        sort(A.begin(), A.end()); // 快速排序
        return A;
    }
};

正确思路:

 双指针法:数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间;
 定义 i 指向起始位置,j 指向终止位置;定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置
class Solution {
public:
    vector<int> sortedSquares(vector<int>& A) {
        int k = A.size() - 1;
        vector<int> result(A.size(), 0);
        for (int i = 0, j = A.size() - 1; i <= j;) { // 注意这里要i <= j,因为最后要处理两个元素
            if (A[i] * A[i] < A[j] * A[j])  {
                result[k--] = A[j] * A[j];
                j--;
            }
            else {
                result[k--] = A[i] * A[i];
                i++;
            }
        }
        return result;
    }
};

209.长度最小的子数组:

在这里插入图片描述

刚看题的思路

使用两个for循环,第一层的for循环,不断的寻找符合条件的子序列,时间复杂度很明显是O(n^2)
class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
            sum = 0;
            for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
                sum += nums[j];
                if (sum >= s) { // 一旦发现子序列和超过了s,更新result
                    subLength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
                }
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

正确思路

滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果;
         只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置;
 重点:滑动窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
       窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)
       窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引
 理解点:滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置

59.螺旋矩阵II:

在这里插入图片描述

刚看题的思路

无思路

正确思路

 求解本题依然是要坚持循环不变量原则。
 模拟顺时针画矩阵的过程:
    填充上行从左到右
    填充右列从上到下
    填充下行从右到左
    填充左列从下到上
    由外向内一圈一圈这么画下去
// 坚持循环不变量原则 左闭右开
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {  // 二维容器 n行,列数不固定
        vector< vector<int> > res(n, vector<int>(n,0)); // 使用一个vector去定义一个二维数组
        int startx = 0 , starty = 0; // 定义每循环一个圈的起始位置
        int loop = n /2;  // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
        int mid = n /2;   // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
        int count = 1;
        int offset = 1;
        int i ,j;
        while(loop--){
            i = startx;
            j = starty;
            
            // 下面开始的四个for就是模拟转了一圈
            // 模拟填充上行从左到右(左闭右开)
            for(j; j< n -offset; j++ ){
                res[i][j] = count++;
            }
            // 模拟填充右列从上到下(左闭右开)
            for(i; i< n -offset; i++ ){
                res[i][j] = count++;
            }
            // 模拟填充下行从右到左(左闭右开)
            for(; j > starty; j-- ){
                res[i][j] = count++;
            }
            // 模拟填充左列从下到上(左闭右开)
            for(; i > startx; i-- ){
                res[i][j] = count++;
            }

            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
            startx++;
            starty++;

            // offset 控制每一圈里每一条边遍历的长度
            offset += 1;
        }
        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
        if(n % 2){
            res[mid][mid] = count; 
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值