代码随想录 9.21 || 数组 LeetCode 977.有序数组的平方、209. 长度最小的子数组、59.螺旋矩阵Ⅱ

LeetCode 977 有序数组的平方

题目链接:704.有序数组的平方

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

题目分析:“非递减顺序”排序的整数数组,数组中含有负数,该整数数组平方后的值,两边高,中间低。解法一:将数组中的每个值平方,然后对新数组排序即可,时间复杂度为O(n+nlogn)。解法二:利用头指针和尾指针,分别指向数组头和尾,然后依次头元素和尾元素平方的大小,将大的值保存在新数组尾部,然后滑动头指针和尾指针,时间复杂度为O(n)。

解法一:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        for(int i = 0; i < nums.size(); i++) {
            nums[i] *= nums[i];
        }
        sort(nums.begin(), nums.end());
        return nums;
    }
};

解法二:

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

LeetCode 209 长度最小的子数组

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

题目要求:给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其总和大于等于target的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回0。

题目分析:该题的解法较多,可以嵌套循环暴力枚举出以每个元素开头符合要求的子数组,时间复杂度为O(n^2);另一种解法,通过快和慢的双指针控制一个滑动窗口,先移动fast指针,直到窗口内的元素总和符合要求,记录此时的窗口长度为子数组长度;然后,移动slow指针,判定窗口内元素综合和target之间的关系,并继续移动slow指针,小于则移动fast指针。在上述过程中,同步更新子数组长度,选取最小的窗口长度作为子数组长度。循环往复,直到fast指针走到最后。

暴力解法:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum;
        int subLength = 0;
        int minLength = 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;
                minLength = minLength < subLength ? minLength : subLength;
                break;
            }
        }
    }
    return minLength == INT_MAX ? 0 : minLength;
    }
};

快慢指针:可以实现为双循环控制和单循环控制,双循环逻辑思清晰,单循环稍有复杂。

class Solution { \\双循环
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int minLength = INT32_MAX, subLength;
        int sum = 0;
        int slow = 0, fast = 0;
        while(fast < nums.size()) { \\双循环,外层循环控制快指针,计算窗口内元素总和num
            sum += nums[fast++];
            while(sum >= target) { \\当sum大于target时,计算subLength,并移动慢指针
                subLength = fast - slow;
                minLength = minLength < subLength ? minLength : subLength;
                sum -= nums[slow++];
            }
        }
        return minLength == INT32_MAX ? 0 : minLength;
    }
};


class Solution { \\单循环
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int minLength = INT32_MAX, subLength;
        int sum = 0;
        int slow = 0, fast = 0;
        while(fast < nums.size() || sum >= target) { \\单循环控制,fast不能超过数组长,特殊情况,fast过界,但是因为else操作的是上次fast的状态,所以也应该进入循环
            if(sum < target) {
                sum += nums[fast++];
            }else{
                subLength = fast - slow; \\else操作的是上次fast的状态,所以subLength不加1
                minLength = minLength < subLength ? minLength : subLength;
                sum -= nums[slow++];
            }
        }
        return minLength == INT_MAX ? 0 : minLength;
    }
};

LeetCode 59 螺旋矩阵Ⅱ

题目连接:59.螺旋矩阵Ⅱ

题目要求:给你一个正整数n,生成一个包含1到n^2所有元素,且元素按照顺时针螺旋排列的n \times n正方形矩阵matrix,如图所示。

题目分析:该题思想不难,难点在于控制边界条件,顺时针转圈赋值。这里约定每次沿着边长的赋值步长为该行(列)的第一个元素~该行(列)的倒数第二个元素,行(列)的最后一个元素作为下一次步长的起点,正方形有四个边,所以转一次圈需要走四次;每次转弯一圈,沿着矩阵对角线顺序,更新下一次的起点;第一圈的步长为n-1,第二圈的步长为n-2,以此类推,共转n/2圈,第n/2的步长为n - n/2。这里存在一个问题,如果n为偶数,则转完圈,矩阵的每个元素都被赋值,如果为n为奇数,则矩阵正中间的值空缺,此时应该手动赋值。实现如下。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int startx = 0, starty = 0;
        int count = 1;
        int offset = 1;
        int loop = n / 2 ;

        while(loop--) {
            int i = startx, j = starty;
            
            for(; j < n - offset; j++) {
                res[i][j] = count++;
            }
            for(; i < n - offset; i++) {
                res[i][j] = count++;
            }
            for(; j > starty; j--) {
                res[i][j] = count++;
            }
            for(; i > startx; i--) {
                res[i][j] = count++;
            }

            startx++;
            starty++;
            offset++;
        }

        if(n % 2){
            res[n / 2][n / 2] = count;
        }
        return res;
    }
};

        数组内容的总结,数组作为基础的数据结构,主要考察对于代码的掌控能力,要熟记数组结构的特点,数组下标从0开始,数组存储空间连续,可以随机存取,数组元素只能覆盖,不能删除,数组定长,等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值