第二天 | 977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵II

977.有序数组的平方

题目链接:

尝试解答:定义两个指针一个指向头(left),一个指向尾(right)。nums[left]和nums[fight]进行比较,较大数放入前端。然后做死了。

思路:

        1.如何想到用双指针,对于题目中可能存在负数,整个数组平方后呈现两边大中间小,故想到两个指针同时向中间靠拢。

        2.如何解决数组填充顺序问题:两头指向中间的过程中先指到较大的数,但题目要求从小到大排列,故令k = nums.size() - 1,反着填充数组。

        3.for循环的弹出条件:i <= j而不是i < j, 若是后者则在i =  j时这个数没有被装进去。

        4.其实在尝试解答时完全是自己想多了,题目并没有要求原地更新数组,所以可以重新开辟一个vector,将元素按顺序向该vector里填充。这样这个题在思路上就没有什么难度了。

第一次代码写成了这样:出现了空指针异常的情况。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> result;                    //没有说明result的内存。
        int index = nums.size() - 1;
        for(int i = 0, j = nums.size() - 1; i <= j; ){
            if(nums[i] * nums[i] >= nums[j] * nums[j]){
                result[index--] = nums[i] * nums[i];
                i++;
            }else{
                result[index--] = nums[j] * nums[j];
                j--;
            }
        }
        return result;
    }
};

对比标准代码是在vector定义时出了问题。

改正后:(这种错误的原因是在栈和队列时习惯性的定义方式,在栈和队列的库函数内部会进行内存的分配,所以不会空指针异常,但在这道题这种情况需要提前分配够内存)

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> result(nums.size(), 0);
        int index = nums.size() - 1;
        for(int i = 0, j = nums.size() - 1; i <= j; ){
            if(nums[i] * nums[i] >= nums[j] * nums[j]){
                result[index--] = nums[i] * nums[i];
                i++;
            }else{
                result[index--] = nums[j] * nums[j];
                j--;
            }
        }
        return result;
    }
};

209.长度最小的子数组(滑动窗口)

题目链接:209. 长度最小的子数组

BF解法:两个for循环

双指针:一个for循环

思路:

滑动窗口:最重要的精髓——如何移动起始位置

                起始位置何时移动?当终止位置移动到目前已遍历的数组元素和大于目标之后,起始位置开始移动、

                关键点:for循环的索引一定指向的是滑动窗口的终止位置。

                易错提醒:起始位置是一个持续的向后移动的过程,故应该用while循环移动起始位置,而是不if(如果是if则只移动一次,可能还不是最短的情况)

                总结:

                        窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

                        窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。

                        窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

代码如下:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int length = INT_MAX, sum = 0;
        for(int last = 0, first = 0; last < nums.size(); last++){
            sum += nums[last];
            while(sum >= target){
                length = min(length, last - first + 1);
                sum -= nums[first];
                first++;
            }
        }
        return length == INT_MAX ? 0 : length;
    }
};

自己写代码时出现了两处问题:

        1.一开始在while循环里没有取 = 。起始sum == target时此时窗口已经满足条件了,故要将此时的窗口长度last - first + 1与之前的最短窗口length作比较。

        2.不知道不存在满足题意的窗口的测试组怎样返回0,见上面答案。

59.螺旋矩阵(***语法上易错,逻辑细节容易理不清,值得多次复习***)

题目链接:59. 螺旋矩阵 II

尝试解答:

        问题:1.怎样定义新的vector<vector<int>> result ?

                   2.在向上向下转角处怎样装填数组?

重点:1.转圈时如何处理边界条件——遵循循环不变量原则,每一次循环都是同样的规则。本题都是左闭右开,最后一个点留给下一条边处理.

           2.使用while循环

           3.定义多少个变量,怎样定义变量,每一轮while循环变量做怎样的变化,才能实现一圈一圈走的逻辑。

           4.如果边长是单数,存放最中间的数字的语法易错。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result(n, vector<int>(n, 0));
        int start_x = 0, start_y = 0, offset = 1, count = 1;
        int i = 0, j = 0, loop = n / 2;        //分别定义i, j,分开指示行列
        while(loop--){      //设置loop变量,判断循环次数
            j = start_y;
            i = start_x;    //必须在此处就将i,j的值更新
            for(; j < n - offset; j++){
                result[i][j] = count++;
            }
            for(; i < n - offset; i++){
                result[i][j] = count++;
            }
            for(j = n - offset; j > start_y; j--){
                result[i][j] = count++;
            }
            for(i = n - offset; i > start_x; i--){
                result[i][j] = count++;
            }
            offset++;
            start_x++;
            start_y++;
        }
        if(n % 2 == 1){             //判断是否存在中心数应该用模运算
            int mid = n / 2;
            result[mid][mid] = count;
        }
        return result;
    }
};

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值