代码随想录算法训练营Day2:977.有序数组的平方;209.长度最小的子数组;59.螺旋矩阵

 977.有序数组的平方 ,

        给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

思路:

非递减-->递增

 方法一:双指针

        每个元素平方后,因为是升序数组,所以从两端比较新数组元素的大值。依次放入新数组内。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        //方法一
     int k = nums.size() - 1;
        vector<int> news(nums.size(), 0);		//定义新数组result
//因为是顺序数组,所以从数组比较两端元素来确定最大的新元素
        for (int i = 0, j = nums.size() - 1; i <= j;){
            if (pow(nums[i], 2) < pow(nums[j], 2)){
                news[k--] = pow(nums[j], 2);
                j--;
            }
            else{
                news[k--] = pow(nums[i], 2);
                i++;
            }
        }
        return news;
    }
};

方法二:暴力排序

         先对数组内的元素进行平方运算,后进行升序排序,关于sort()方法的详解参照如下链接:sort()方法

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        for(int i = 0; i < nums.size(); i++){	//先求出平方后的数组
            nums[i] = pow(nums[i], 2);
        }
//对数组进行快速排序,默认升序
        sort(nums.begin(), nums.end());
        return nums;
    }
};

209.长度最小的子数组 

        给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

错误思路:(忽略连续子数组

步骤1:进行倒序排序,

步骤2:在循环中,查找是否有大于等于target的单个元素

       有,则输出“1“;无,则进行下一步骤

步骤3:固定第一个元素,逐步与下一个元素相加,直到>=target

//错误解法(忽略连续子数组)
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i=0,flag=0,sum=0;
        struct
        {
            bool operator()(int a, int b) const { return a > b; }
        }descMax;
        sort(nums.begin(),nums.end(),descMax);
        int k=nums.size();
        if(nums[i]>=target){
            flag=1;
        }else{
            sum=nums[i];
            for(i=1;i<k;i++){
                sum+=nums[i];
                if(sum>=target){
                    flag= 2;
                    break;
                }
            }
        }
        return flag >0 ? i+1 : 0;
    }
};

 正确解法:

    连续的最小长度的元素之和大于target

方法一:暴力解法

        一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。

//方法一:暴力法
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int size= nums.size();
        if (size == 0) {    //不存在符合条件的子数组,返回 0
            return 0;
        }
        int result= INT_MAX;    //最终结果
        for (int i = 0; i < size; i++) {
            int sum = 0;    //每次求和前,清零
            for (int j = i; j < size; j++) {
                sum += nums[j];
                if (sum >= target) {
                    // result = min(result, j - i + 1); 
                    //判断每次当子数组之和大于target后的长度偏小的子数组的长度
                    result=result<j-i+1?result:j-i+1;
                    break;      
                    //因为要求长度最小,且在循环求和中,子数组长度地递增,
                    //所以每次符合条件“子数组之和大于target “,即可结束当前子循环
                }
            }
        }
        //验证result有无被赋值,有则返回result值,无则返回0,
        return result == INT_MAX ? 0 : result;
    }
};

 备注:暴力解法超时

方法二:滑动窗口

        不断的调节子序列的起始位置和终止位置

关键代码块:

for (int j = 0; j < nums.size(); j++) {

            sum += nums[j];

            while (sum >= s) {          //  每次更新 i(起始位置),并不断比较子序列是否符合条件

                subLength = (j - i + 1); // 取子序列的长度

                result = result < subLength ? result : subLength;

                sum -= nums[i++]; // 不断变更i(子序列的起始位置)

            }

        }

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX;
        int sum = 0; // 滑动窗口数值之和
        int i = 0; // 滑动窗口起始位置
        int subLength = 0; // 滑动窗口的长度
        for (int j = 0; j < nums.size(); j++) {
            sum += nums[j];
            // while,每次更新 i(起始位置),并不断比较子序列是否符合条件
            while (sum >= s) {
                subLength = (j - i + 1); // 取子序列的长度
                result = result < subLength ? result : subLength;
                sum -= nums[i++]; // 不断变更i(子序列的起始位置)
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

59.螺旋矩阵 

   给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

思路:

01 02

04 03

01 02 03

08 09 04

07 06 05

01 02 03 04

12 13 14 05

11 16 15 06

10 09 08 07

01 02 03 04 05

16 17 18 19 06

15 24 25 20 07

14 23 22 21 08

13 12 11 10 09 

坚持不变量原则:

    模拟顺时针绘制矩阵,有四种路线:

    从左到右,从上到下,从右到左,从下到上,由外及内。

随想录中提到的左闭右开,左开右闭,主要针对的是,在不同路线的拐弯处,所统一采取的原则,如图

依据代码随想录的思路:

    首先判断矩阵可以绕几圈:n/2

    n%2>0:n为奇数,最后剩的一个数在中间;

下列代码采取左闭右开的原则。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        //定义二维数组
        vector<vector<int>> res(n, vector<int>(n, 0));  

        int loop=0;//标记循环的次数
        int count=1;//显示的数值
        // int starx=0,stary=n-1;//循环的初始状态(0,n-1);
        int start=0;
        int mid=n/2;
        int i,j;
        while(loop++<=mid){
            
            //从左右
            for(j=start;j<n-loop;j++){
                res[start][j]=count++;
            }
         
            //从上下
            for(i=start;i<n-loop;i++){
                res[i][j]=count++;
            }
        
            //从右左
           for(;j>=loop;j--){
                res[i][j]=count++;
            }
           
            //从下上
             for(;i>=loop;i--){
                res[i][j]=count++;
            }
            start++;
            
        }
        if(n%2){
            res[mid][mid]=count;
        }
        return res;
    }
};

疑难

        起初,我以为每个数的起点是(0,n-1),可是编译后的结果很让我疑惑,至今我也不明白为什么从左到右的路径的代码会是:

for(j=start;j<n-loop;j++){

     res[start][j]=count++;

 }

我总会写成这样:

for(i=start;i<n-loop;i++){

     res[i][star]=count++;

 }

  在此过程中我遇到了这样一个报错,

        使用了AddressSanitizer检查是否存在内存非法访问,该问题检查内存非法访问问题。查阅过资料,有的博客是这么解决的:点击

        而我的问题则是因为代码逻辑问题,导致矩阵某些位置的值重叠了。通常是位于for循环语句的条件判断是否要加等号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值