代码随想录算法训练营第二天| 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

977.有序数组的平方

题目链接:977. 有序数组的平方 - 力扣(LeetCode)
文档讲解:代码随想录 (programmercarl.com)
视频讲解:双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili
解题思路:

int* sortedSquares(int* nums, int numsSize, int* returnSize) {
    int *goal = (int*)malloc(sizeof(int)*numsSize); //创建新数组 
    int k = numsSize - 1; //下标索引
    for (int i = 0, j = numsSize - 1; i <= j ; ) { //头尾指针
        if (nums[i]*nums[i] > nums[j]*nums[j]) { //比较头尾平方的大小
            goal[k--] = nums[i]*nums[i];
            i++;
        } else {
            goal[k--] = nums[j]*nums[j];
            j--;
        }
    }
    *returnSize = numsSize;
    return goal;
}


时间复杂度:O(n)
该题总结:听了视频讲解以后思路就很清晰的一道题,由于C语言没有数组排序的函数,我就没写暴力解法。

209.长度最小的子数组

题目链接:209. 长度最小的子数组 - 力扣(LeetCode)
文档讲解:代码随想录 (programmercarl.com)
视频讲解:拿下滑动窗口! | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili
解题思路:

//暴力解法
int minSubArrayLen(int target, int* nums, int numsSize) {
    int storage = INT_MAX;  //存储长度最小的子数组段
    for (int i = 0; i < numsSize; i++) {    
        int sum = 0;
        for(int j = i; j < numsSize; j++) {
            sum += nums[j];
            if (sum >= target) {
                int length = j - i + 1; //当前子数组的长度
                storage = storage > length ? length : storage;  //更新最小长度
            }
        }
    }
    return storage == INT_MAX ? 0 : storage;    //用于判断是否存在符合条件的子数组,不存在则返回0
}

//这个暴力解法在leetcode上会超出时间限制,只作参考
//滑动窗口
int minSubArrayLen(int target, int* nums, int numsSize) {
    int storage = INT32_MAX;    //用来与滑动窗口的长度作比较,并寄存滑动窗口的最小长度
    int sum = 0;    //滑动窗口的和
    int suml = 0;   //滑动窗口的长度
    for (int i=0,j=0; j<numsSize; j++) {    //定义滑动窗口的双指针,i为起始指针,j为结束指针
        sum += nums[j]; //滑动窗口和的算法
        while (sum >= target) { //判断滑动窗口的和是否大于目标值
            suml = j - i + 1;   //滑动窗口的长度算法
            sum -= nums[i]; //减去起始指针的值,再重新判断sum于target的大小
            i++;    //起始指针后移一位
            storage = storage < suml ? storage : suml;//比较并存储storage与suml的更小的那个值
        }
    }
    return storage == INT32_MAX ? 0 : storage;//用于判断是否存在符合条件的子数组,不存在则返回0
}


时间复杂度:O(n)
该题总结:对于我这种小白来说时间复杂度都弄不清楚,我本来以为两个循环嵌套时间复杂度就会是O(n^2),但查找资料后发现不只是要考虑嵌套关系,还要考虑整体的执行次数。这题更重要的是滑动窗口的解题思路,滑动窗口本身是双指针法的一种,这种解法让该题思路非常清晰。

59.螺旋矩阵II

题目链接:59. 螺旋矩阵 II - 力扣(LeetCode)
文档讲解:代码随想录 (programmercarl.com)
视频讲解:一入循环深似海 | LeetCode:59.螺旋矩阵II_哔哩哔哩_bilibili
解题思路:

int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
    int startx = 0,starty = 0;  //设置起始位置
    *returnSize = n; //告诉leetcode这个螺旋矩阵有几行
    *returnColumnSizes = (int*)malloc(sizeof(int) * n);   //申请列数的内存
    int offset = 1; //循环一圈之后需要缩小的区间
    int loop = n / 2; //需要循环的圈数
    int count = 1;  //螺旋矩阵中填入的数字
    int mid = n / 2;    //如果矩阵大小为奇数,需要用mid来填入正中间那个空位置
    int **ans =  (int**)malloc(sizeof(int*)*n);  //申请螺旋矩阵每一行的内存

    for (int i=0; i<n ;i++) {
        ans[i] = (int*)malloc(sizeof(int)*n);   //为螺旋矩阵申请每一列的所需内存
        (*returnColumnSizes)[i] = n; //告诉leetcode这个螺旋矩阵每行有几列
    }

    //  上面都是准备工作,现在才是开始

    while(loop) {
        int i = startx,j = starty;
        for(; j < n - offset; j++) { //往右走,左闭右开,不走到头
            ans[i][j] = count++;
        }
        for(; i < n - offset; i++) {   //往下走
            ans[i][j] = count++;
        }
        for(; j > starty; j--) {   //往左走
            ans[i][j] = count++;
        }
        for(; i > startx; i--) {   //往上走
            ans[i][j] = count++;
        }
        offset++;   //缩小边界
        loop--; 
        startx++;   //这里绝对不要让i和j自增,不然相当于白做,自然也就错了
        starty++;   //如果非得想让i,j自增的话就把i,j的初始化放到循环外
    }
    if (n % 2 != 0) {   //若矩阵为奇数则需要在矩阵的中心额外加上一位count
        ans[mid][mid] = count++;
    }
    return ans;
}


时间复杂度:O(n^2)
该题总结:这题是耗时最长的一题,不止在于这个螺旋矩阵的实现耗时,真正难住我的是如何用malloc申请二维数组的空间,一开始我都没有看出来,这道题其实有两个二维数组,一个是用来实现螺旋矩阵的二维数组,另一个是用来告诉leetcode这个螺旋矩阵有多大的二维数组,我理解这个用了好长时间,不过还好最后是实现了这个螺旋矩阵,它的实现虽然稍微碰上了一些问题,已经在代码注释上标出来了,但还好最后还是清楚明白地做出来了,实现这个螺旋矩阵最重要的还是在二分法里学过的循环不变量原则。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值