代码随想录算法训练营day2

1.长度最小的子数组

1.1 题目链接

. - 力扣(LeetCode)

1.2 思路

滑动窗口

1.3 题解

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int slow=0;
        int fast=0;
        int sum=0;
        int result=INT32_MAX;
        int length=0;
        while(fast<nums.size())
        {
            sum+=nums[fast];
            while(sum>=target)
            {
                length=fast-slow+1;
                if(length<result)
                {
                    result=length;
                }
                sum-=nums[slow];
                slow++;
            }
            fast++;
        }

        if(result==INT32_MAX)
        {
            return 0;
        }
        return result;
    }
};

1.4 解释

定义一个快指针和慢指针,实际上可以看作一个滑动窗口,不断计算快指针与慢指针之间的元素和,如果和大于或等于target的值,就更新窗口的长度并减去慢指针所处位置的值。

1.5 复杂度

时间复杂度为O(n)

2.螺旋矩阵

2.1 题目链接

. - 力扣(LeetCode)

2.2 思路

以每一圈为一个任务,每一圈中再分为四条边,注意循环不变量左闭右开。

2.3 题解

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) 
    {
        /*左闭右开写法*/

        // 构建2维数组
        vector<vector<int>> result(n,vector<int>(n,0));
        // 边起始位置
        int startx = 0;
        int starty = 0;
        // 边终止偏移量
        int offset = 1;
        // 数值
        int count = 1;
        //要转的圈数
        int loop=n/2;

        int x,y;

        // 要转的圈数为循环条件
        while (loop--) 
        {
            x = startx;
            y = starty;

            // 从左到右第一条边
            for (; x < n - offset; x++) 
            {
                result[y][x] = count++;
            }
            // 从上到下第二条边
            for (; y < n - offset; y++) 
            {
                result[y][x] = count++;
            }
            // 从右到左第三条边
            for (; x > startx; x--) 
            {
                result[y][x] = count++;
            }
            // 从下到上第四条边
            for (; y > starty; y--) 
            {
                result[y][x] = count++;
            }
            startx++;
            starty++;
            offset++;
        }
        //为奇数的情况下
        if (n % 2 == 1) 
        {
            result[n / 2][n / 2] = n * n;
        }
        return result;
    }
};

2.4 复杂度

时间复杂度为O(n^{2})

),相当于遍历2维数组。

3.区间和

3.1 题目链接

58. 区间和(第九期模拟笔试)

3.2 思路

先计算前缀和,之后利用前缀和相减就能得出结果

3.3 题解

#define _CRT_SECURE_NO_WARNINGS  //防止在VS中报错:scanf是不安全的。VS中有一个独有的scanf_s,只能在VS上运行
using namespace std;
#include <iostream>
#include <vector>


int main()
{


    //数组的长度
    int n;
    
    //输入的左区间
    int left;
    //输入的右区间
    int right;
    //从控制台输入数组长度
    scanf("%d", &n);
    vector<int> vec(n);

    int input;
    int add=0;

    //输入数组的元素
    for (int i = 0; i < n; i++)
    {
        //求前缀和之后再放入数组

        scanf("%d", &input);
        add += input;
        vec[i] = add;
    }

    
    //输入左右区间
    while (~scanf("%d%d", &left,&right))//当报错时,scanf一般会返回-1,但是在while循环中,-1仍然会继续循环,所以应该用符号~取其二进制反码使其为0从而循环停止
    {
        int sum;
        //左边界为0时要单独考虑
        if (left == 0)
        {
            sum = vec[right];
        }
        else
        {
            sum = vec[right] - vec[left - 1];
        }
        
        printf("%d\n", sum);
    }
    
}

3.4 解释

比如说区间[a,b],先求原数组的前缀和得到一个新数组,那么区间[a,b]之间的和就等同于新数组索引b处的元素减去索引a-1处元素。

4.开发商购买土地

4.1 题目链接

44. 开发商购买土地(第五期模拟笔试)

4.2 思路

可以考虑前缀和,分别求出纵向和横向的前缀和数组。

4.3 题解

#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#include <iostream>
#include <vector>


int main()
{
    int n;
    int m;

    cin >> n >> m;
    vector<vector<int>> vec(n, vector<int>(m, 0));
    //构建二维数组
    for (int i = 0; i < n; i++)
    {
        
        for (int j = 0; j < m; j++)
        {
            cin >> vec[i][j];

        }
    }

    //求纵向前缀和数组
    //先构建数组
    vector<int> vec_x;
    int csum1 = 0;
    for (int i = 0; i < n; i++)
    {
        int sum_x = 0;
        for (int j = 0; j < m; j++)
        {
            sum_x += vec[i][j];

        }
        csum1 += sum_x;

        vec_x.push_back(csum1);
    }
    
    //求横向前缀和数组
    //先构建数组
    vector<int> vec_y;
    int csum2 = 0;
    for (int i = 0; i < m; i++)
    {
        int sum_y = 0;
        for (int j = 0; j < n; j++)
        {
            sum_y += vec[j][i];
        }
        csum2 += sum_y;

        vec_y.push_back(csum2);
    }

    //纵向分割
    int result1 = INT32_MAX;
    int min_split1 = 0;
    //有n-1种分法
    for (int i = 0; i < n-1; i++)
    {
        //前半部分的和
        int sum_begin = vec_x[i];
        //后半部分的和
        int sum_end = vec_x[n-1] - vec_x[i];

        //求差值,注意使用绝对值
        min_split1 = abs(sum_end - sum_begin);

        if (min_split1 < result1)
        {
            result1 = min_split1;
        }
    }

    //纵向分割
    int result2 = INT32_MAX;
    int min_split2 = 0;
    //有n-1种分法
    for (int i = 0; i < m-1; i++)
    {
        //前半部分的和
        int sum_begin = vec_y[i];

        //后半部分的和
        int sum_end = vec_y[m - 1] - vec_y[i];


        //求差值,注意使用绝对值
        min_split2 = abs(sum_end - sum_begin);


        if (min_split2 < result2)
        {
            result2 = min_split2;
        }
    }

    int res= result1 > result2 ? result2 : result1;
    cout << res << endl;

   
}

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值