您现在的位置是:首页 >技术杂谈 >代码随想录算法训练营第二天|977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II网站首页技术杂谈
代码随想录算法训练营第二天|977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
目录
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. 找到第一个非负数后使用双指针
先用二分法找到第一个非负数;在第一个非负数的位置和其前一个位置设置指针,边比较边存。
这个其实和用首尾指针其实没一点区别,一个从内向外比较,一个从外向内,但是比首尾指针繁琐的多。
二分法时间复杂度:O(logn);比较和存的过程时间复杂度:O(n)。整体时间复杂度:O(n)。
//二分法找到第一个非负数所在下标
int Find_positive(int *nums,int numsSize){
int left=0;
int right=numsSize-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]==0) return mid;
if(nums[mid]>0) right=mid-1;
if(nums[mid]<0) left=mid+1;
}
return left;
}
int* sortedSquares(int* nums, int numsSize, int* returnSize){
int *ret=(int *)malloc(sizeof(int)*numsSize);
*returnSize=0;
int num=Find_positive(nums,numsSize);
int left=num-1;
int right=num;
while(left>=0&&right<numsSize){
int a=nums[left]*nums[left];
int b=nums[right]*nums[right];
if(a>b){
ret[(*returnSize)++]=b;
right++;
}else{
ret[(*returnSize)++]=a;
left--;
}
}
//对剩余未进行比较元素进行处理
while(left>=0){
ret[(*returnSize)++]=nums[left]*nums[left];
left--;
}
while(right<numsSize){
ret[(*returnSize)++]=nums[right]*nums[right];
right++;
}
return ret;
}
3.仅使用首尾指针
注意到数组本身是有序的,最大值只可能在首尾取到。开辟额外空间,利用首尾指针边比较边存。
时间复杂度:O(n)
int* sortedSquares(int* nums, int numsSize, int* returnSize){
int *ret=(int *)malloc(sizeof(int)*numsSize);
*returnSize=numsSize;
int sign=numsSize;
int *left=nums;
int *right=&nums[numsSize-1];
while(left<=right){
if((*left)*(*left)>=(*right)*(*right)){
ret[--sign]=(*left)*(*left);
left++;
}else{
ret[--sign]=(*right)*(*right);
right--;
}
}
return ret;
}
209.长度最小的子数组(难度:中,不会)
题目链接:力扣
题目描述:给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:输入:target = 7,nums = [2,3,1,2,4,3]
输出:2
解释:子数组[4,3]是该条件下最小的子数组。
1.暴力(超时)
int minSubArrayLen(int target, int* nums, int numsSize){
int min=INT_MAX; //初始结果设为无穷大,便于比较
for(int i=0;i<numsSize;i++){
int sum=0;
for(int j=i;j<numsSize;j++){ //双层循环控制分别从每一位开始加
if((sum+=nums[j])>=target){
min=fmin(min,j-i+1); //j-i+1表示加了多少个数
break;
}
}
}
if(min==INT_MAX){ //最终结果还是无穷大,说明不存在子数组和不小于目标值
return 0;
}else{
return min;
}
}
2.滑动窗口
这个得再多看看
暴力法使用双层循环,对其进行改进省去一层循环,只能是省去对起始位置的遍历。
设置终止位置j从0到numsSize-1,找的情况。之后再去确定i的位置,只要和sum>=target,就减去最前面的一个数,用i来标记,初值设为0,满足条件就加1。
int minSubArrayLen(int target, int* nums, int numsSize){
int min=INT_MAX;
int i=0;
int sum=0;
for(int j=0;j<numsSize;j++){ //j指终止位置
sum+=nums[j];
while(sum>=target){ //找到以0为起始,j为终止的和不小于目标值的元素个数
min=fmin(min,j-i+1); //也就是j-i+1,再考虑从下标0开始每次去除一个元素
sum-=nums[i++]; //sum相应减去对应值,如果仍然不小于目标值,起始位置加1
}
}
if(min==INT_MAX){
return 0;
}else{
return min;
}
}
59.螺旋矩阵II(难度:中)
题目链接:力扣
题目描述:给你一个正整数
n
,生成一个包含1
到n2
所有元素,且元素按顺时针顺序螺旋排列的n x n
正方形矩阵matrix
。
示例:输入:n=3
输出:[[1,2,3],[8,9,4],[7,6,5]]
如下图所示。
对于偏移数的设置与代码随想录中不同,我觉得设为1更容易理解。这个不会就看一遍视频吧!
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
*returnSize=n;
*returnColumnSizes=(int *)malloc(sizeof(int)*n);
int ** nums=(int **)malloc(sizeof(int*)*n);
for(int i=0;i<n;i++){ //初始化结果数组
nums[i]=(int *)malloc(sizeof(int)*n);
(*returnColumnSizes)[i]=n;
}
int sign=1; //偏移数为1
int digit=1; //初始值为1
int loop=n/2; //表明需要转几圈
int startx=0,starty=0;
while(loop){
int i,j;
for(j=starty;j<n-sign;j++){
nums[startx][j]=digit++;
}
for(i=startx;i<n-sign;i++){
nums[i][j]=digit++;
}
for(;j>starty;j--){
nums[i][j]=digit++;
}
for(;i>startx;i--){
nums[i][j]=digit++;
}
sign++; //偏移数每次加1
startx++;starty++;loop--;
}
if(n%2!=0){ //如果n是奇数,最后会空出中心位置
nums[startx][starty]=digit;
}
return nums;
}
相关题目
54.螺旋矩阵
这种东西最好只出现在程序填空里面
int* spiralOrder(int** matrix, int matrixSize, int* matrixColSize, int* returnSize){
int *ret=(int *)malloc(sizeof(int)*(matrixSize*(*matrixColSize)));
int index=0;
int sign=1; //偏移量
int loop=fmin(matrixSize,(*matrixColSize))/2; //遍历圈数
int num=fmin(matrixSize,*matrixColSize);
int startx=0,starty=0; //初始位置
int i,j;
while(loop){
for(j=starty;j<(*matrixColSize)-sign;j++){
ret[index++]=matrix[startx][j];
}
for(i=startx;i<matrixSize-sign;i++){
ret[index++]=matrix[i][j];
}
for(;j>starty;j--){
ret[index++]=matrix[i][j];
}
for(;i>startx;i--){
ret[index++]=matrix[i][j];
}
startx++;starty++;sign++;loop--;
}
if(num%2!=0){
if(matrixSize>(*matrixColSize)){
for(i=startx;i<=matrixSize-sign;i++){
ret[index++]=matrix[i][starty];
}
}else{
for(j=starty;j<=(*matrixColSize)-sign;j++){
ret[index++]=matrix[startx][j];
}
}
}
*returnSize=index;
return ret;
}
其他
qsort()快排
void qsort (
void* base, //要排序的目标数组
size_t num, //待排序的元素个数
size_t width, //一个元素的大小,单位是字节
int(*cmp)(const void* e1, const void* e2));
cmp是函数指针,指向比较两元素的函数,需要自己写
整形:
int cmp_int(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2; //升序
}
字符型:
int cmp_char(const void* e1, const void* e2)
{
return *(char*)e1 - *(char*)e2;
}
字符串型:(字符串比较用strcmp)
int cmp_str(const void* e1, const void* e2)
{
return strcmp(*(char**)e1, *(char**)e2);
}
创建二维动态数组
int ** nums=(int **)malloc(sizeof(int*)*n);
for(int i=0;i<n;i++){
nums[i]=(int *)malloc(sizeof(int)*n);
}