977.有序数组的平方
题目LeetCode977. 有序数组的平方
双指针思路
由于平方后两边的元素最大,中间的元素最小,所以可以使用双指针。
- 定义left指向原数组最左边,right指向原数组最右边
- 比较left元素的平方和right元素的平方
- left元素平方大于right元素平方,将left元素平方放在结果集最后,left++
- right元素平方大于left元素平方,将right元素平方放在结果集最后,right–
代码
int* sortedSquares(int* nums, int numsSize, int* returnSize){
int left = 0;
int right = numsSize - 1;
int* res = (int*)malloc(sizeof(int) * numsSize);
*returnSize = 0;
//数组平方
for (int i = 0; i < numsSize; i++)
nums[i] *= nums[i];
while (left <= right)
{
if (nums[left] > nums[right])
res[numsSize - 1 - (*returnSize)++] = nums[left++];
else
res[numsSize - 1 - (*returnSize)++] = nums[right--];
}
return res;
}
209.长度最小的子数组
题目:LeetCode209. 长度最小的子数组
暴力解法
这道题目暴力解法当然是 两个for循环,然后从整个数组头不断的寻找符合条件的子序列,时间复杂度很明显是O(n^2)。
int minSubArrayLen(int target, int* nums, int numsSize) {
//暴力:
int subSum = 0;//记录子串和
int sublen = 0;//记录子串长度
int res = INT_MAX;
for (int i = 0; i < numsSize; i++)//循环变量记录子串头
{
subSum = 0;//每一次子串头更新时字串和更新为0
for (int j = i; j < numsSize; j++)//循环变量记录子串尾
{
subSum += nums[j];
if (subSum >= target)//子串和超过目标值
{
sublen = j - i + 1;//统计子串长度
res = res < sublen ? res : sublen;//记录最短字串长度
break;//找到最短长度后直接break
}
}
}
//最短字串长度没有改变的话说明不存在子数组满足条件
return res == INT_MAX ? 0 : res;
}
滑动窗口⭐️
滑动窗口,就是不断条件子串的起始位置和结束位置,从而得出我们想要的结果。
暴力解法中使用了两层for循环,而滑动窗口只使用一层for循环完成了两层循环所做的事,所以请思考滑动窗口的一层for循环中的循环变量代表着什么?循环变量代表的是窗口(子串)的尾点
- 如果循环变量代表的是起始点,那么我们仍然需要一个循环变量来记录窗口的尾点,这样的做法就和暴力解法一样需要另外一层for循环寻找窗口的尾点
- 如果循环变量表示窗口的尾点,那么我们只需要一个变量记录窗口的起始点,滑动窗口的关键问题就是如何变化窗口的起始点
问题就是如何表示滑动窗口的起始位置?
这里还是以题目中的示例来举例,s=7, 数组是 2,3,1,2,4,3,来看一下查找的过程
最后找到3 4是最短子串
这个思路的关键三个点就是
- 什么是窗口?
- 如何移动窗口的起始位置
- 如何移动窗口的终止位置?
- 窗口就是满足元素之和大于等于target的子串
- 当窗口的值大于等于target时窗口的起始位置向每次后移动一格
- 当窗口的值小于target时窗口的终止位置向后移动一格
int minSubArrayLen(int target, int* nums, int numsSize) {
//滑动窗口
int subSum = 0;//记录子串和
int res = INT_MAX;
int sublen = 0;//记录子串长度
int i = 0;//记录滑动窗口起始位置
for (int j = 0; j < numsSize; j++)//循环变量是滑动窗口结束位置
{
subSum += nums[j];//统计子串和
//子串和大于等于target
while (subSum >= target)
{
sublen = j - i + 1;//字串长度
subSum -= nums[i];//字串和减去窗口当前起始位置的值
i++;//窗口起始位置向前滑动一个位置
res = res < sublen ? res : sublen;//记录最小字串长度
}
}
return res == INT_MAX ? 0 : res;//res没变表示不存在这样的子串
}
59.螺旋矩阵
题目LeetCode59. 螺旋矩阵 II
思路
很容易观察到矩阵的值是随着每一圈而增加的,所以我们可以外面一个大的循环表示循环的圈数,至于每一圈怎么处理是我们要讨论的重点
- 每一圈可以分为4个方向,左到右、上到下、右到左、下到上
- 每一个方向处理的数据不能有重复
我们可以通过每次处理一个方向的数据是左闭右开的来保证每个方向处理到的数据不会有重复,而我们在处理过程中是一定要执行这个左闭右开的原则,这就是循环不变量
文章来源:https://www.toymoban.com/news/detail-426449.html
代码
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
//初始化返回的结果数组的大小
*returnSize = n;
*returnColumnSizes = (int*)malloc(sizeof(int) * n);
//初始化返回结果数组ans
int** martix = (int**)malloc(sizeof(int*) * n);
int i;
for(i = 0; i < n; i++) {
martix[i] = (int*)malloc(sizeof(int) * n);
(*returnColumnSizes)[i] = n;
}
int loop = n / 2;//循环loop圈
int curNum = 1;//当前填充值
for (int count = 0; count < loop; count++)
{
//初始化一圈的开始坐标
int i = count, j = count;
//保持左闭右开的原则从左向右赋值
for ( ; j < n - 1 - count; j++) martix[i][j] = curNum++;
//保持左闭右开的原则从上向下赋值
for ( ; i < n - 1 - count; i++) martix[i][j] = curNum++;
//保持左闭右开的元组从右向左赋值
for ( ; j > count; j--) martix[i][j] = curNum++;
//保持左闭右开的原则从下向上赋值
for ( ; i > count; i--) martix[i][j] = curNum++;
}
//填充奇数圈正中间的值
if (n % 2 == 1) martix[loop][loop] = curNum++;
return martix;
}
文章来源地址https://www.toymoban.com/news/detail-426449.html
到了这里,关于代码随想录【数组】----->有序数组的平方、长度最小的子数组、螺旋矩阵的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!