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这个螺旋矩阵有多大的二维数组,我理解这个用了好长时间,不过还好最后是实现了这个螺旋矩阵,它的实现虽然稍微碰上了一些问题,已经在代码注释上标出来了,但还好最后还是清楚明白地做出来了,实现这个螺旋矩阵最重要的还是在二分法里学过的循环不变量原则。