目录

209. 长度最小的子数组

双指针解法

59. 螺旋矩阵II

模拟解法

区间和

前缀和解法

开发商购买土地

前缀和解法


209. 长度最小的子数组

双指针解法

这道题考察的是双指针。

如果使用两个for循环遍历,就相当于一开始i指针在数组的首端,另外一个j指针遍历其后的情况,下一次循环i再慢慢地后移;

我们使用一个for循环j指针遍历数组,并把j指针所在的位置看成是子数组的末端,子数组的首端设置为i指针,只有在子数组的长度大于等于target才更新,就可以使用一个for循环干两个for循环的事情。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT32_MAX;
        int i = 0; int sum = 0; int subLength = 0;
        for (int j = 0; j < nums.size(); j++) {
            sum += nums[j];
            while (sum >= target) {
                subLength = j - i + 1;
                result = min(result, subLength);
                sum-=nums[i++];
            }
        }
        return result == INT32_MAX? 0 : result;
    }
};

59. 螺旋矩阵II

模拟解法

这道题是一道模拟题,考查边界条件的处理。每一圈拆成4个循环,依次对答案数组进行赋值。值得一提的是,当n为单数时,数组中心只有一个值,需要单独考虑。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> resMat(n, vector<int>(n, 0));
        int maxLoopTime = n / 2;
        int iterationNum = 1;
        for(int loop = 0; loop < maxLoopTime; loop++) {
            int thisLoopPieceLength = n - 1 - loop *2;
            for (int j = loop; j < loop + thisLoopPieceLength; j++) {
                resMat[loop][j] = iterationNum;
                iterationNum++;
            }
            for (int i = loop; i < loop + thisLoopPieceLength; i++) {
                resMat[i][thisLoopPieceLength + loop] = iterationNum;
                iterationNum++;
            }
            for (int j = thisLoopPieceLength + loop; j > loop; j--) {
                resMat[thisLoopPieceLength + loop][j] = iterationNum;
                iterationNum++;
            }

            for (int i = thisLoopPieceLength + loop; i > loop; i--) {
                resMat[i][loop] = iterationNum;
                iterationNum++;
            }
        }
        if(n % 2 != 0) {
            resMat[n/2][n/2] = iterationNum;
        }
        return resMat;
    }
};

区间和

前缀和解法

前缀和不解释。

没想到有朝一日我也成为记事本仙人了。。

#include <iostream>
#include <vector>
using namespace std;
int main () {
int n, cur, a, b;
cin >> n;
vector<long long> _sum(n, 0);
for (int i = 0; i < n; i++) {
cin >> cur;
if ( i == 0) _sum[i] = cur;
else {
 _sum[i] = _sum[i-1] + cur;
}
}
while (cin >> a >> b) {
if (a == 0) cout << _sum[b] << endl;
else cout << _sum[b] - _sum[a-1] << endl;
}
return 0;
}

开发商购买土地

文章讲解:

https://www.programmercarl.com/kamacoder/0044.%E5%BC%80%E5%8F%91%E5%95%86%E8%B4%AD%E4%B9%B0%E5%9C%9F%E5%9C%B0.html

前缀和解法

1. 在读取数组元素的循环中,记录元素总和sum。

2. 使用两个一维数组,一个记录每行元素之和,一个记录每列元素之和。

3. 分别遍历两个数组,使用一个变量cur_cut,每轮循环加上轮到的数组元素,来表示开发商A分了多少地。abs(sum - cur_cut - cur_cut)就是题目所说的“ A 公司和 B 公司各自的子区域内的土地总价值之差”,在循环中不断地寻找最小值就行了。

(一不小心就用成下划线的变量命名法了)

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

using namespace std;
int main() {
    int n, m;
    cin >> n >> m;
    vector <vector<int>> vec(n, vector<int> (m, 0));
    int sum = 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> sum_horizontal(n, 0);
    vector<int> sum_vertical(m, 0);


    for (int i = 0; i < n; i++) 
        for (int j = 0; j < m; j++) 
        sum_horizontal[i] += vec[i][j];

    for (int j = 0; j < m; j++) 
        for (int i = 0; i < n; i++) 
            sum_vertical[j] += vec[i][j];

    int min_gap = INT_MAX;
    int cur_cut = 0;

    for(int j = 0; j < m; j++) {
        cur_cut += sum_vertical[j];
        min_gap = min(min_gap, abs(sum - cur_cut - cur_cut));
    }

    cur_cut = 0;
    for (int i = 0; i < n; i++) {
        cur_cut += sum_horizontal[i];
        min_gap = min(min_gap, abs(sum - cur_cut - cur_cut));
    }

    cout << min_gap << endl;

return 0;
}
posted on 2026-01-15 23:41  快乐的乙炔  阅读(1)  评论(0)    收藏  举报  来源