代码随想录算法 Day2 | 209. 长度最小的子数组,59. 螺旋矩阵Ⅱ ,7.区间和,44.开发商购买土地

一、长度最小的子数组

        1.题目:给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

2.思路: 滑动窗口 

3.注意:

 (1)所示代码中for循环内判断条件用while而不是if

        循环体内使用 if 时,窗口左边界移动一次后尚未判断新窗口内子数组元素和是否 >= target 就会将右边界移动。

        本人原本使用 if 思路:for 循环的第三个部分对窗口右边界移动的部分不写,然后窗口左边界移动后继续执行循环体,待符合条件的子数组变成不符合条件后再将右边界移动。

 (2)对返回值的取值

        本人起初是令返回值 numLenth 初始化时为 0,此时 while 循环体内的 if 判断会永远为假,所以修改为初始化为 nums.size(),但如下方代码中注释部分所示,在 return 时当 numLenth 为初始值时需要两层判断,所以最后将 numLenth 初始化为比 nums.size() 大的数值即可。

4.代码

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int left=0,right=0;
        int numLenth = nums.size() + 1;
        int numsCount = 0;
        int numsCount2 = 0;
        int numsL,numsR;

        for( right=0; right<nums.size(); right++)
        {
            numsCount = numsCount + nums[right];
            // numsCount2 = numsCount2 + nums[right];
            while( numsCount >= target )
            {
                if( numLenth > (right - left + 1) )
                {
                    numsL = left;
                    numsR = right;
                    numLenth = right -left + 1;
                }

                numsCount = numsCount - nums[left];
                left++;
            }  

        }

        return ( numLenth > nums.size() )?0:numLenth;

        // if(numLenth < nums.size())
        // {
        //     return numLenth;
        // }else{
        //     return ( numsCount2 >= target )?nums.size():0;
        // }
        
    }
};

二、螺旋矩阵Ⅱ

        1.题目:给你一个正整数 n ,生成一个包含 1 到 所有元素,且元素按顺时针顺序螺旋排列的 n*n 正方形矩阵 matrix 。

2.思路: 模拟运行即可

3.注意:

(1)思考循环不变量的使用

(2)n为奇数时需要单独给正中心的格子赋值

4.代码

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result(n, vector<int>(n,0));
        int startX,startY;
        int i,j;
        int loop = n/2;
        int mid = n/2;
        int count = 1;
        int offset = 1;

        while( loop-- )
        {   
            i = startX;
            j = startY;

            // 填上方
            for(j; j < n-offset; j++)
            {
                result[i][j] = count++;
            }

            // 填右侧
            for(i; i < n - offset; i++)
            {
                result[i][j] = count++;
            }

            // 填下方
            for(; j > startY; j--)
            {
                result[i][j] = count++;
            }

            // 填左侧
            for(; i > startX; i--)
            {
                result[i][j] = count++;
            }

            // 循环一圈后需要进行的处理
            startX++;
            startY++;

            offset++;
        }

        // n为奇数时,循环绕圈会漏掉最中心的格子
        if( n % 2 )
        {
            result[mid][mid] = count;
        }

        return result;
    }
};

三、区间和

        1.题目:给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。

        输入描述:

        第一行输入为整数数组 Array 的长度 n,接下来 n 行,每行一个整数,表示数组的元素。随后的输入为需要计算总和的区间,直至文件结束。

        输出描述:

        输出每个指定区间内元素的总和。

2.思路: 前缀和

3.注意:

 (1)了解ACM答题模式,笔试/面试必备

 (2)C++在面对大量数据的输入输出时,使用 scanf 和 printf 比 cin 和 cout 少很多时间

4.代码

#include <iostream>
#include <vector>
using namespace std;
int main() {
    int n, a, b;
    cin >> n;
    vector<int> vec(n);
    vector<int> p(n);
    int presum = 0;
    for (int i = 0; i < n; i++) {
        cin >> vec[i];
        // scanf("%d", &vec[i]);
        presum += vec[i];
        p[i] = presum;
    }

    while (cin >> a >> b) {
        int sum;
        if (a == 0) sum = p[b];
        else sum = p[b] - p[a - 1];
        cout << sum << endl;
        // printf("%d\n", sum);
    }
}

四、开发商购买土地问题

        1.题目:在一个城市区域内,被划分成了n * m个连续的区块,每个区块都拥有不同的权值,代表着其土地价值。目前,有两家开发公司,A 公司和 B 公司,希望购买这个城市区域的土地。现在,需要将这个城市区域的所有区块分配给 A 公司和 B 公司。然而,由于城市规划的限制,只允许将区域按横向或纵向划分成两个子区域,而且每个子区域都必须包含一个或多个区块。为了确保公平竞争,你需要找到一种分配方式,使得 A 公司和 B 公司各自的子区域内的土地总价值之差最小。 Ps:区块不可再分。

        输入描述:

        第一行输入两个正整数,代表 n 和 m。

        接下来的 n 行,每行输出 m 个正整数。

        输出描述:

        请输出一个整数,代表两个子区域内土地总价值之间的最小差距。

        2.思路

        3.注意

        4.代码

#include <iostream>
#include <vector>
#include <climits>

using namespace std;
int main () {
    int n, m;
    cin >> n >> m;
    int sum = 0;
    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];
            sum += vec[i][j];
        }
    }
    // 统计横向
    vector<int> horizontal(n, 0);
    for (int i = 0; i < n; i++) {
        for (int j = 0 ; j < m; j++) {
            horizontal[i] += vec[i][j];
        }
    }
    // 统计纵向
    vector<int> vertical(m , 0);
    for (int j = 0; j < m; j++) {
        for (int i = 0 ; i < n; i++) {
            vertical[j] += vec[i][j];
        }
    }
    int result = INT_MAX;
    int horizontalCut = 0;
    for (int i = 0 ; i < n; i++) {
        horizontalCut += horizontal[i];
        result = min(result, abs(sum - horizontalCut - horizontalCut));
    }
    int verticalCut = 0;
    for (int j = 0; j < m; j++) {
        verticalCut += vertical[j];
        result = min(result, abs(sum - verticalCut - verticalCut));
    }
    cout << result << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值