代码随想录算法训练营第二天| 977.有序数组的平方、209.长度最小的子数组 、59.螺旋矩阵 II
1. 977.有序数组的平方
题目:给定一个按非递减顺序排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
思路1:最直接想到的是首先对数组的每个数据平方,然后重新排序,这样带来的时间复杂度主要取决于排序算法的复杂度。具体代码如下:
int* sortedSquares(int* nums, int numsSize, int* returnSize){
void sort(int array[],int num);
*returnSize = numsSize;
int *p;
p = (int *)calloc(sizeof(int) , 10000);
for(int i = 0; i < numsSize; i++) {
p[i] = nums[i] * nums[i];
}
sort(p,numsSize);
return p;
}
void sort(int array[],int num)
{
int t;
for(int i = 0; i < num - 1; i++)
for(int j = 0; j < num - i - 1; j++ ) {
if(array[j] > array[j+1]) {
t = array[j];
array[j] = array[j+1];
array[j+1] = t;
}
}
}
- 时间复杂度:O(nlog n)
思路2:另一种方法是采用双指针法,由于nums中的元素是按非递减顺序排序的,因此元素平方后,最大值一定在数组两边的位置,最小值在数组中间的位置,因此定义两个指针分别指向数组两边,然后逐步向中间移动,每次将两个指针指向的元素平方值更大的结果放在新数组中,并更新相应的指针。代码如下所示:
int* sortedSquares(int* nums, int numsSize, int* returnSize){
int *p, k, left, right;
p = (int *)calloc(sizeof(int),10000);
*returnSize = numsSize;
for(left = 0, right = numsSize - 1, k = numsSize - 1; left <= right;) {
if(nums[left] * nums[left] > nums[right] * nums[right]) {
p[k--] = nums[left] * nums[left];
left++;
}
else {
p[k--] = nums[right] * nums[right];
right--;
}
}
return p;
}
- 时间复杂度:O(n)
2. 209.长度最小的子数组
题目:给定一个含有 n 个正整数的数组和一个正整数 s,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
思路1:直接的想法是采用两个for循环暴力求解,不断地寻找符合条件的子序列,具体代码如下所示:
int minSubArrayLen(int target, int* nums, int numsSize){
int len_min = numsSize+1, sum, flag;
for (int i = 0; i < numsSize; i++) {
int len = 0;
sum = 0;
flag = 0;
for (int j = i; j < numsSize; j++) {
len++;
sum += nums[j];
if (sum >= target){
flag = 1;
break;
}
}
if(flag)
len_min = len_min > len ? len : len_min;
}
if(len_min>numsSize)
return 0 ;
else
return len_min;
}
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
注意:Leetcode上这道题采用暴力解法会超时。
思路2:另一种方法是滑动窗口法(双指针法的一种),其采用一个for循环完成了之前两个for循环完成的工作。重点是明确for循环里循环索引表示的应该是滑动窗口的终止位置(若为起始位置,则与两个for循环的逻辑类似)。起始位置的移动则取决于当前窗口的值的大小,若当前窗口的值大于s,窗口就要向前移动(也就是该缩小了)。代码如下:
int minSubArrayLen(int target, int* nums, int numsSize){
int left = 0, sum = 0, flag = 0, len = numsSize;
for(int i = 0; i < numsSize; i++) {
sum += nums[i];
while(sum >= target) {
len = len < i - left + 1 ? len : i - left + 1;
sum -= nums[left++];
flag = 1;
}
}
if(flag)
return len;
else
return 0;
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)
3. 59.螺旋矩阵 II
题目:(模拟题)给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
思路:重点是遵循循环不变量原则,处理边界条件时要一直遵循左闭右开或左开右闭的准则。代码如下:
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
*returnSize = n;
*returnColumnSizes = (int*)malloc(sizeof(int) * n);
//初始化返回结果数组ans
int** ans = (int**)malloc(sizeof(int*) * n);
int i;
for(i = 0; i < n; i++) {
ans[i] = (int*)malloc(sizeof(int) * n);
(*returnColumnSizes)[i] = n;
}
int startx = 0, starty = 0, offset = 1, loop = n/2, count = 1;
while(loop) {
int i = startx, j = starty;
for(; j < n - offset; j++)
ans[startx][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++;
startx++;
starty++;
offset++;
loop--;
}
if(n%2)
ans[startx][starty] = count;
return ans;
}
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)