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

977有序数组的平方

977. Squares of a Sorted Array两种解法

重点(缺一不可,否则不会返回数组):

【最好在函数开头就申明】*returnSize = numsSize;//返回数组的长度等于数组nums的长度

int* ans = (int*)malloc(sizeof(int) * numsSize);//需要重新申请一个同样大小的数组返回,即使不申请也可以通过,但不符合要求

注:

1读清要求:新建数组需要分配空间存放结果,而不是在原数组作修改。Note: The returned array must be malloced, assume caller calls free().

2要用*returnSize = numsSize;返回数组的大小。

3malloc是c语言中的动态分配内存,result=(int*)malloc(sizeof(int)2);malloc函数返回的是void型,所以要强制类型转换成int,在前面加上(int%20*),才能给整型赋值,后面(sizeof(int)*2)的意思是分配两个int大小的空间。

4在C语言中,*= 是一种复合赋值运算符,它表示将左操作数乘以右操作数并将结果赋值给左操作数。例如,a *= 2 等价于 a = a * 2

1.暴力解法

原理:先平方后排序
在这里插入图片描述

2.双指针法

原理:比较两端数的平方大小得到未排序序列中的最大值放到未排序序列末端
在这里插入图片描述

209.长度最小的子数组

注:A subarray is a contiguous non-empty sequence of elements within an array.子数组是数组中连续的非空元素序列。

1暴力算法

思路:找每个数组元素大于等于target的子数组最小长度,找到就和已储存的最小长度进行比较和更新,并继续找下个元素满足条件的子数组最小长度

在这里插入图片描述

int minSubArrayLen(int target, int* nums, int numsSize) {
    int sum=0;
    //找出从i开始长度为n的连续子集的和,一旦发现大于等于target就返回n。
    for(int n=1;n<=numsSize;n++){
        for(int x=0;x<=numsSize-n;x++){
            for(int i=x;i<=x+n-1;i++){
                sum+=nums[i];
            }
            if(sum>=target){
                return n;
            }else{
                sum=0;
            }
        }
    }
    return 0;
}

关于将多行代码左移或者右移一个TAB制表符https://www.cnblogs.com/RexTooru/p/9803257.html

左移的话是按下Ctrl+[,右移可以直接按tab也可以用Ctrl+]。

在这里插入图片描述

int minSubArrayLen(int target, int* nums, int numsSize) {
    int sum=0;
    int n=0;
    int min=numsSize+1;
    //找每个数组元素大于等于target的子数组最小长度
    //找到就和已储存的最小长度进行比较和更新
    //并继续找下个元素满足条件的子数组最小长度
    //初始数组元素下标为x,sum的末尾元素下标为y
    for(int x=0;x<numsSize;x++){
        sum=0;
        for(int y=x;y<numsSize;y++){
            sum+=nums[y];
            if(sum>=target){
                n=y-x+1;
                if(n<min){
                    min=n;
                    break;
                }
            }
        }  
    }
    if(min==numsSize+1){
        return 0;
    }else{
        return min;
    }
}
2滑动窗口

确实很巧妙!既找到了每个数组元素起始的满足条件的子数组最小长度,又找到了其中最小的值作为原数组中满足条件的子数组最小长度

//先找第一个数组元素的最小长度

//再减去第一个数组元素即把起始元素后移查看是否还能满足条件能得到更小长度

//如果不行了的话就开始找此时初始数组元素的最小长度

//如果可以就继续更新初始数组元素和最小长度在这里插入图片描述

int minSubArrayLen(int target, int* nums, int numsSize) {
    int sum=0;
    int n=0;
    int min=numsSize+1;
    //先找第一个数组元素的最小长度
    //再减去第一个数组元素即把起始元素后移查看是否还能满足条件能得到更小长度
    //如果不行了的话就开始找此时初始数组元素的最小长度
    //如果可以就继续更新初始数组元素和最小长度
    for(int x=0,y=0;y<numsSize;y++){
        sum+=nums[y];
        while(sum>=target){
            n=y-x+1;
            if(min>n){
                min=n;
            }
            sum-=nums[x++];
        }
    }
    if(min==numsSize+1){
        return 0;
    }else{
        return min;
    }
}

59螺旋矩阵II

59. Spiral Matrix II,一种解法

在这里插入图片描述

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
    //把数值依次填入它应该在的地方,左闭右开进行顺时针赋值
    //ans是一个指向指针的指针,定义二级数组存放每一行的首地址,申请了n个int*的空间,申请的二维数组有n行
    //*returnSize指针指向的是数组的行,*returnColumnSizes 是数组的大小
    *returnSize=n;
    *returnColumnSizes=(int*)malloc(sizeof(int)*n);
    int** ans=(int**)malloc(sizeof(int*)*n);
    //为每一行数据申请列的空间,有n列
    for(int i=0;i<n;i++){
        ans[i]=(int*)malloc(sizeof(int)*n);
        (*returnColumnSizes)[i]=n;
    }
    //设置循环起始位置
    int startX=0;//每转一圈横纵坐标的最小值要增大1格
    int startY=0;
    //设置循环末尾位置的偏移值
    int offset=0;//每转一圈横纵坐标的最大值要缩小1格
    int loop=n/2;//n为偶数时圈数为n/2,n为奇数时圈数为(n-1)/2,因为多了一个中间值
    int x=0;//定义x为行数,y为列数
    int y=0;
    int count=1;
    while(loop--){
        //记得每次开始新的一圈的时候要重新定位初始位置!
        x=startX;
        y=startY;
        for(;y<n-1-offset;y++){
            ans[x][y]=count++;
        }
        for(;x<n-1-offset;x++){
            ans[x][y]=count++;
        }
        for(;y>startY;y--){
            ans[x][y]=count++;
        }
        for(;x>startX;x--){
            ans[x][y]=count++;
        }
        startX++;
        startY++;
        offset++;
    }
    //如果n是奇数,需要处理多出来的中间值
    if(n%2){
        ans[n/2][n/2]=count;
    }
    return ans;
}
知识点

动态定义一个m行, n列的2维数组(经典面试题)https://blog.youkuaiyun.com/qq_70799748/article/details/127130061
在这里插入图片描述

二维数组a中存放的是数组每行的首地址,长度为二维数组的行数i;a[i]数组中存放的则是数组第i行数组元素的地址,长度为二维数组的列数j。

因为不知道数组元素的类型所以无法知道大小,需要在程序中进行动态申请空间malloc,而不能像int i一样定义完就行。

二级指针和内存申请模板https://blog.youkuaiyun.com/m0_61159638/article/details/122006715
在这里插入图片描述

在学习一级指针的时候,我们用*进行解引用,变成普通变量,二级指针经过一次解引用,变成一级指针。

int **myMalloc(int r, int c, int* returnSize, int** returnColumnSizes) {
    int i;
    int **ret = (int **)malloc( sizeof(int *) * r );       
    *returnColumnSizes = (int *)malloc( sizeof(int) * r ); 
    *returnSize = r;                                       
    for(i = 0; i < r; ++i) {
        ret[i] = (int *)malloc( sizeof(int) * c );         
        (*returnColumnSizes)[i] = c;                       
    }    
    return ret;
}

malloc的意义https://blog.youkuaiyun.com/m0_62969222/article/details/122268331

如果直接在函数中定义一个二维数组,最后将它返回,这样写对吗?很显然这样不对,因为在该函数中定义一个二维数组是在栈区开辟的一块儿空间,只要走出了这个函数,这块儿空间就会被释放掉。所以我们不能在栈区开辟空间,要在堆区开辟空间,即通过malloc,calloc,realloc。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值