有序数组的平方
- 前提
- 有序数组
- 要点
- 记得用传入的指针返回新数组长度
- 有序数组平方后最大值只会在首尾两端,不会再中间
暴力解法
新数组先赋值再排序
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
int *returnArray = malloc(sizeof(int)*numsSize);
*returnSize = numsSize;
for (int i = 0; i < numsSize; i++){
returnArray[i] = nums[i]*nums[i];
}
for (int i = 0; i < numsSize-1; i++){
for (int j = i+1; j < numsSize; j++){
if (returnArray[i] > returnArray[j]){
int cur = returnArray[i];
returnArray[i] = returnArray[j];
returnArray[j] = cur;
}
}
}
return returnArray;
}
双指针法
相向双指针
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
int *returnArray = malloc(sizeof(int)*numsSize);
int i =0;
int j = numsSize - 1;
int k = numsSize - 1;
*returnSize = numsSize;
while(i <= j){
if ((nums[i]*nums[i]) < (nums[j]*nums[j])){
returnArray[k--] = nums[j]*nums[j];
j--;
}
else{
returnArray[k--] = nums[i]*nums[i];
i++;
}
}
return returnArray;
}
长度最小的子数组
- 前提
- 正整数数组
- 要点
- 总和大于等于 target的长度最小的连续子数组
- 滑动窗口
- 窗口即子数组
- 终点指针随着for循环索引移动,扩大窗口,寻找总和大于等于target的子数组
- 找到这样的子数组后,起始指针移动,缩小窗口,寻找符合条件长度最小的子数组
暴力解法(超时)
int minSubArrayLen(int target, int* nums, int numsSize) {
int i = 0;
int j = 0;
int result = numsSize + 1;
int subSize = 0;
int sum = 0;
for (i = 0; i < numsSize; i++){
sum = 0;
for (j = i; j < numsSize; j++){
sum += nums[j];
if (sum >= target){
subSize = j - i + 1;
result = result < subSize? result:subSize;
break;
}
}
}
return result > numsSize? 0:result;
}
滑动窗口
int minSubArrayLen(int target, int* nums, int numsSize)
{
int start = 0, end = 0;
int sum = 0;
int subSize = 0;
int result = INT_MAX;
for (; end < numsSize; end++){
sum += nums[end];
while (sum >= target){
subSize = end - start + 1;
result = result < subSize ? result : subSize;
sum -= nums[start++];
}
}
return result == INT_MAX ? 0 : result;
}
此处使用while,时间复杂度是2n,不是n*n。
螺旋矩阵 2
- 前提
- 要点
- 坚持循环不变原则,一则n=奇数时中间一个单独填,方便循环圈数与n=偶数时对齐;二则四条边都是左闭右开;三则是坐标、偏移量、loop这套模型的复用。
- 注意函数后两个传参是利用指针(&取地址)返回结果
模拟行为
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
*returnSize = n;
*returnColumnSizes = malloc(sizeof(int*)*n);
int **ans = malloc(sizeof(int*)*n);
for (int i = 0; i < n; i++){
ans[i] = malloc(sizeof(int)*n);
(*returnColumnSizes)[i] = n;
}
int startX = 0;
int startY = 0;
int offset = 1;
int loop = n/2;
int count = 1;
int mid = n/2;
while (loop){
int i = startX;
int j = startY;
for (;j < startY + n - offset; j++){
ans[startX][j] = count++;
}
for (; i < startX + n - offset; i++){
ans[i][j] = count++;
}
for (;j > startY; j--){
ans[i][j] = count++;
}
for (;i > startX; i--){
ans[i][startY] = count++;
}
startX++;
startY++;
offset += 2;
loop--;
}
if (n%2){
ans[mid][mid] = count;
}
return ans;
}
总结
- 数组两个必不可少的参数:起始地址和Size(限定有效区域)
- 循环不变量原则:整齐复用
- 双指针法:同向(移除重复)、相向(平方排序)、滑动窗口(连续子集)
- 模拟行为:循环体内的步骤边界分明,衔接干净流畅