代码随想录算法训练营第二天| 209.长度最小的子数组、59.螺旋矩阵II、区间和、开发商购买土地

209.长度最小的子数组

题目链接:209. 长度最小的子数组 - 力扣(LeetCode)

讲解链接:代码随想录

视频链接:

问题所在:没有梳理清楚整个代码逻辑,虽然理解题意,要素都在,但排列顺序有问题;应通过举例子顺一遍,应该先让指针右移递加,一旦和满足要求(>=target),首先计算此时长度,比较选取和上一次的最小值;先删除此时左指针元素,减小长度用于下一次判断;然后在处理left左指针,left++(先处理left会导致长度不是此时符合要求的长度;以及)

关键点:滑动窗口,分清左右两指针的作用,因此判断清楚循环递增变量用哪一个

重点理解while循环内的逻辑

答案:

int minSubArrayLen(int target, int* nums, int numsSize) {
    int sum = 0;
    int left = 0;
    int right = 0;
    int length = INT_MAX;

    for(right=0;right<numsSize;right++){
        printf("%d %d", right, sum);
        sum = sum + nums[right];
        while(sum>=target){
            if(length>=(right - left+1)){
                length = right - left+1;
            }
            sum = sum - nums[left];
            left++;
        }
        
    }
    return length == INT_MAX ? 0 : length;

}

59.螺旋矩阵II

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:一入循环深似海 | LeetCode:59.螺旋矩阵II_哔哩哔哩_bilibili

问题所在:会写for,但是不知道怎么转起来,走一圈一般是while

关键点:保持统一规则,循环不变量,类似二分法规定好区间定义;

首先转几圈?n/2圈,如果n为奇数(n%2==1),最后单独赋值;

考虑起始和终止位置,用while让它转起来

答案:(先复制下来,动态分配内存还不会写)

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;
    int startY = 0;
    //设置二维数组的中间值,若n为奇数。需要最后在中间填入数字
    int mid = n / 2;
    //循环圈数
    int loop = n / 2;
    //偏移数
    int offset = 1;
    //当前要添加的元素
    int count = 1;

    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][j] = count++;
        }
        //偏移值每次加2
        offset+=2;
        //遍历起始位置每次+1
        startX++;
        startY++;
        loop--;
    }
    //若n为奇数需要单独给矩阵中间赋值
    if(n%2)
        ans[mid][mid] = count;

    return ans;
}

区间和

讲解链接:58. 区间和 | 代码随想录 (programmercarl.com)

关键点:

利用前缀和,遍历一遍,边读取边加和,前缀和相减得到区间和。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int n;
    scanf("%d", &n);
    
    int *vec = (int *)malloc(sizeof(int) * n);
    int *p = (int *)malloc(sizeof(int) * n);
    
    int presum = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d", &vec[i]);
        presum += vec[i];
        p[i] = presum;
    }
    
    int a, b;
    while (scanf("%d %d", &a, &b) == 2) {
        int sum;
        if (a == 0) {
            sum = p[b];
        } else {
            sum = p[b] - p[a - 1];
        }
        printf("%d\n", sum);
    }

    free(vec);
    free(p);

    return 0;
}

开发商购买土地

讲解链接:44. 开发商购买土地 | 代码随想录 (programmercarl.com)

关键点:同样利用区间和的思想,计算好每一行或者每一列的和,做差即可

第一章总结 - 数组

卡哥总结:代码随想录 (programmercarl.com)

另外需要注意的点:

1.掌握好数组的地址、值、下标之间的关系

2.动态分配内存

3.for和while的选用

4.二维数组的格式

5.思考复杂度是怎么得来的

第二天感受:

实际上昨天被209卡住了,明明要素都在,运行不正确,有点心浮气躁,一行一行对比也没发现问题;第三天才解决,逐行比较发现逻辑错误,处理指针的语句先后问题----一定要梳理好整个过程的逻辑,如果过于抽象难以想像,建议用图形或者例子辅助理解;一遍很难全部明白,进度有点慢了,没懂的地方要来回看两三遍;看过视频理解逻辑不代表会写,很多细节需要注意的,定期看题目回想大概要怎么做,形成一个惯性或者解题流程。

ps:代码出错的时候--1.逐行对比  2.看不懂丢给GPT   3.学会自己debug打印参数(很尴尬的是C语言printf我加了&,打印一堆地址出来) 4.群里描述清楚请教大佬解答

第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小数组,使得数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值