代码随想录day2 数组进阶

977 有序数组的平方

题目

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

示例:输入:nums = [-4,-1,0,3,10],输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]

思考

刚看到这题时发现只要将原数组所有元素平方后再排序就完事了,但要求是用双指针来解答,思考良久,核心点在于不明白双指针不仅可以从同一起点出发,也可以从数组的前后两端向中间进行遍历,这题就是很好的例子,本题需要注意的有三点:
1、本题不存在快慢指针,只有左右指针,右指针的初始值在数组尾部

2、本题while循环的条件是left<=right,如果没有等于的话会少最后的结果会少遍历一个数

3、本题需要创建一个vector来存放结果,当得到结果时用 vector[pos] = 结果 的方式来存放,pos的位置可以从0也可以从vector尾部开始

代码

class Solution {

public:

    vector<int> sortedSquares(vector<int> &nums)

    {

        vector<int> res(nums.size());

        int left = 0, right = nums.size() - 1, pos = nums.size() - 1;

        while (left <= right) {

            if (abs(nums[left]) > abs(nums[right]))

                res[pos--] = pow(nums[left++], 2);

            else

                res[pos--] = pow(nums[right--], 2);

        }

        return res;

    }

};

209 长度最小的子数组

题目

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

示例:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组[4,3]是该条件下的长度最小的子数组

思考

本题有暴力和滑窗两种解法,我个人更倾向于滑窗法,其实滑窗和双指针很类似,同样都是用两个指针来进行遍历,区别是双指针在得到结果时是某一个数,而滑窗是左右指针截取的一段数组,滑窗法的基本步骤如下:

1、确定快慢指针:和双指针类似,一般都从数组头部或者一头一尾开始遍历

2、确定while循环条件:一般是right < nums.size()

3、根据题目要求来进行相应的计算处理,本题逻辑是当累加的和sum >= target时,对左指针进行右移操作,目的是找到最小长度的子数组

代码

// 滑窗法

class Solution {

public:

    int minSubArrayLen(int target, vector<int> &nums)

    {

        // right是终止位置,res必须要设成int型最大值,因为刚开始要判断他是否大于sublength

        int left = 0, right = 0, sum = 0, sublength = 0, res = INT_MAX;

        while (right < nums.size()) {

            sum += nums[right];

            // 这里用while很关键,目的是在找到对应target的数组后再进一步看看有没有更小数组

            while (sum >= target) {

                sublength = right - left + 1;

                res = min(res, sublength);

                sum -= nums[left++];

            }

            right++;

        }

        // 这里的目的是搜索完整个nums没有找到对应的数组后返回0

        return res == INT_MAX ? 0 : res;

    }

};

// 暴力

class Solution {

public:

    int minSubArrayLen(int target, vector<int> &nums)

    {

        int sum = 0, sublength = 0, res = INT_MAX;

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

            sum = 0;

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

                sum += nums[j];

                if (sum >= target) {

                    sublength = j - i + 1;

                    res = min(res, sublength);

                    break;

                }

            }

        }

        return res == INT_MAX ? 0 : res;

    }

};

59 螺旋矩阵||

题目

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

思考

初看题目时完全懵,感觉无从下手,只看出来左上、右下和中间的数是啥,后面看了讲解视频才明白具体逻辑,其实就是按照示例1中的方向遍历矩阵的四条边,最外一圈遍历完了再向内一层遍历,需要注意的有两点:

1、每一条边的遍历都是左闭右开,最后一个数(也是下一条边的第一个数)放到下一条边去遍历

2、while循环(即转圈)的次数是n/2:n的平方(所有的数)除以4(四条边)再开方(一层层向内循环)

3、当n是奇数时,最中间也就是数组的最后一个数需要单独填充

代码

class Solution {

public:

    vector<vector<int>> generateMatrix(int n)

    {

        vector<vector<int>> res(n, vector<int>(n, 0));  // res要先赋值,不然会nullptr

        // offset很关键,代表遍历的每一条边有offset个数放到下一条边去遍历,一般都是最后一个数

        int startx = 0, starty = 0, offset = 1, count = 1;  

        int r = 0;

        int i, j;  // i,j要先声明,不然第十一行res[i][j]会找不到j是什么

        while (r < n / 2) {

            for (j = starty; j < n - offset; j++)

                res[startx][j] = count++;  // 上边

            for (i = startx; i < n - offset; i++)

                res[i][j] = count++;  // 右边

            for (; j > starty; j--)

                res[i][j] = count++;  // 下边,此循环刚开始时j = n-offset, i = n - offset

            for (; i > startx; i--)

                res[i][j] = count++;  // 左边,此循环开始时i等于n-offset,j = 0

            startx++;

            starty++;

            offset++;

            r++;

        }

        if (n % 2 == 1)

            res[startx][starty] = count;  // 这里是在最中间位置存放数组最后一个数,也可以用res[n/2][n/2]来代替

        return res;

    }

};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值