977.有序数组的平方
题目:给你一个按 非递减顺序 排序的整数数组
nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
暴力解
思路:
首先就想到每个数组平方之后,在进行快速排序即可。
完整代码
#include <stdio.h>
int Partition(int A[],int low,int high);
void QuickSort(int A[],int low,int high);
int* sortedSquares(int* nums, int numsSize, int* returnSize);
int main()
{
int nums[5] = {-7,-3,2,3,11};
int lenth;
int *arr;
arr = sortedSquares(nums,5,&lenth);
for(int i=0;i<lenth;i++)
printf("%4d",arr[i]);
return 0;
}
/***************************************************************
** 功能: 每个元素平方后排序
** 参数: nums:传入数组首地址 numsSize:数组大小 returnSize:返回数组大小
** 返回值: arr:返回平方后递增数组
****************************************************************/
/*暴力解法*/
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
int *arr = NULL;
*returnSize = numsSize;
arr = (int *)malloc(sizeof(int) * numsSize);
for(int i=0;i<numsSize;i++)
{
arr[i] = nums[i] * nums[i];
}
QuickSort(arr,0,numsSize-1);
return arr;
}
void QuickSort(int A[],int low,int high)
{
int pivotpos;
if(low<high)
{
pivotpos = Partition(A,low,high);
QuickSort(A,low,pivotpos-1);
QuickSort(A,pivotpos+1,high);
}
}
int Partition(int A[],int low,int high)
{
int pivot = A[low];
while(low<high)
{
while(low<high&&A[high]>=pivot) --high;
A[low] = A[high];
while (low<high&&A[low]<=pivot) ++low;
A[high] = A[low];
}
A[low] = pivot;
return low;
}
双指针方法
思路:
该数组是非递减存在负数的数组,所以最大的元素一定在两边,从两边开始取数进行平方,比较谁更大,然后放在新的数组中,依次向中间靠拢直到退出循环。
完整代码
#include <stdio.h>
int* sortedSquares(int* nums, int numsSize, int* returnSize);
int main(void)
{
int nums[5] = {-4,-1,0,3,10};
int lenth;
int *arr;
arr = sortedSquares(nums,5,&lenth);
for(int i=0;i<lenth;i++)
printf("%4d",arr[i]);
return 0;
}
/***************************************************************
** 功能: 每个元素平方后排序
** 参数: nums:传入数组首地址 numsSize:数组大小 returnSize:返回数组大小
** 返回值: arr:返回平方后递增数组
****************************************************************/
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
*returnSize = numsSize;//返回数组大小等于传入数组大小
int *arr = (int *)malloc(sizeof (int) * numsSize);//申请与传入数组大小相等的数组空间
int low = 0,high = numsSize-1;
int k = numsSize - 1;//新数组下表,倒序开始
while(low<=high)
{
//如果low的平方大于high的平方
if( (nums[low]*nums[low]) > (nums[high]*nums[high]) )
{
arr[k] = (nums[low]*nums[low]);
low++;//low向中间移动
}
else//这里包含相等的情况
{
arr[k] = (nums[high]*nums[high]);
high--;//high向中间移动
}
k--;//数组下标前移
}
return arr;
}
209.长度最小的子数组
给定一个含有
n
个正整数的数组和一个正整数target
。找出该数组中满足其总和大于等于
target
的长度最小的 连续子数组[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回0
。
暴力解
思路 :
用一个for循环作为起始位置作为外层循环,另一个for循环收集求和,若大于给定值则收集区间长度并且跳出内层循环,直到外层循环遍历整个数组结束,最终取最小值返回,若没有则返回0.
完整代码
#include <stdio.h>
int minSubArrayLen(int target, int* nums, int numsSize);
int main()
{
int arr[6] = {2,3,1,2,4,3};
printf("%d",minSubArrayLen(7,arr,6));
return 0;
}
/***************************************************************
** 功能: 寻找最小的子长度数组
** 参数: target:目标值 nums:传入的数组 numsSize:数组大小
** 返回值: 0:表示没有符合的子数组 非0:表示子数组长度
****************************************************************/
int minSubArrayLen(int target, int* nums, int numsSize) {
int sum = 0;
int result = numsSize;
for(int i = 0;i < numsSize;i++)
{
sum = sum + nums[i];
//判断是否存在子数组
if(sum >= target)
break;
}
if(sum<target)
return 0;
for(int i = 0;i < numsSize;i++)
{
sum = 0;
for(int j = i;j < numsSize;j++)
{
sum = sum + nums[j];
if(sum >= target)
{
//如果result>该长度,则返回该长度,否则不变
result = ( result > (j - i + 1) ) ? ( j - i + 1 ) : result;
//找到之后就结束本次循环,因为在向后增加还是符合题意,只不过不可能是最小
break;
}
}
}
return result;
}
滑动窗口解法
思路:
难点是对谁进行for循环,假设对i进行for循环会发现,j也要for循环才能后使得sum的值增加,这样又会回到暴力解,所以我们只对j进行for循环,还有一个问题就是i的移动到底是移动一次还是一直移动,很明显是一直移动直到不符合题意,
完整代码
#include <stdio.h>
int minSubArrayLen(int target, int* nums, int numsSize);
int main()
{
int arr[6] = {2,3,1,2,4,3};
printf("%d",minSubArrayLen(7,arr,6));
return 0;
}
/***************************************************************
** 功能: 寻找最小的子长度数组
** 参数: target:目标值 nums:传入的数组 numsSize:数组大小
** 返回值: 0:表示没有符合的子数组 非0:表示子数组长度
****************************************************************/
int minSubArrayLen(int target, int* nums, int numsSize) {
int i = 0,sum = 0,result = numsSize;
_Bool flag = 0;//用来判断整个数组是否符合题意
for(int j=0;j<numsSize;j++)
{
sum = sum + nums[j];
while(sum>=target)
{
//符合题意时,起始指针减起始指针的数值,直到不符合题意
sum = sum - nums[i];
//判断是否是最小子数组
if( result > (j-i+1) )
{
result = j-i+1;
}
//起始指针右移动
i++;
//有一次符合就说明该数组一定存在最小子数组,flag设置为1
flag = 1;
}
}
if(flag == 1)
return result;
else
return 0;
}
59.螺旋矩阵II
给你一个正整数
n
,生成一个包含1
到n2
所有元素,且元素按顺时针顺序螺旋排列的n x n
正方形矩阵matrix
。
思路
代码
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
*returnSize = n; // 设置返回数组的大小
// 分配返回数组的列大小
*returnColumnSizes = (int*)malloc(sizeof(int) * n);
// 分配返回数组的空间
int **arr = (int **)malloc(sizeof (int*) * n);
int offset = 1; // 偏移量,用于控制每一圈的起始位置
int x = 0; // 当前位置的行坐标
int y = 0; // 当前位置的列坐标
int count = 1; // 当前要填入的数字
int i = 0, j = 0; // 循环计数变量
int loop = n/2; // 控制循环次数,一共需要循环n/2次
// 分配返回数组的每一行的空间,并设置列大小
for(i = 0; i < n; i++) {
arr[i] = (int*)malloc(sizeof(int) * n);
(*returnColumnSizes)[i] = n;
}
// 根据循环次数进行填充
while(loop)
{
// 填充当前圈的上边
for(j=y;j<n-offset;j++)
arr[x][j] = count++;
// 填充当前圈的右边
for(i=x;i<n-offset;i++)
arr[i][j] = count++;
// 填充当前圈的下边
for(;j>y;j--)
arr[i][j] = count++;
// 填充当前圈的左边
for(;i>x;i--)
arr[i][j] = count++;
// 更新起始位置和偏移量
x++;
y++;
offset--;
loop--;
}
// 如果n为奇数,最后一个位置需要单独填充
if(n%2 != 0)
arr[x][y] = count;
return arr; // 返回生成的数组
}