代码随想录day2

209.长度最小的子数组

第一种写法,最简单理解 时间复杂度O(n^2),无法通过

int minSubArrayLen(int target, vector<int>& nums) {
        int result = 0;
        for(int i = 0; i < nums.size(); i++){
            int ans = nums[i];
            if(ans >= target){
                result = 1;
                break;
            }
            for(int j = i + 1; j < nums.size(); j++){
                ans += nums[j];
                if(ans >= target){
                    if(result == 0){
                        result = j - i + 1;
                    }else{
                        result = min(result, j - i + 1);
                    }
                    break;
                }
            }
        }
        return result;
    }

第二种写法:滑动窗口,理解窗口的概念及如何变化

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

此处也可以考虑倒着从int32_max对比

int minSubArrayLen(int target, vector<int>& nums) {
        int result = 0;
        //int result = INT32_MAX;
        int sum = 0;
        int left = 0;
        for(int right = 0; right < nums.size(); right++){
            sum += nums[right];
            while(sum >= target){
                int count = (right - left + 1);
                result = result == 0 ? count : min(result, count);
                //result = min(result, count);
                sum -= nums[left];
                left++;
            }
        }
        //result = result == INT32_MAX ? 0 : result;
        return result; 

    }

59.螺旋矩阵II

这题主要是要理解螺旋的计算过程,以及写代码时数组的边界控制,以后写数组时注意尽量使用左闭右开

vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> result(n, vector<int>(n, 0));
        int startx = 0, starty = 0;
        int loop = n / 2;
        int offset = 1;
        int count = 1;
        while(loop--){
            int i = startx;
            int 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++;
        }
        if(n%2){
            result[startx][starty] = count;
        }
        return result;
    }

58.区间和:

第一种写法,暴力解法,报超时

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

int main(){
    int length = 0;
    cin >> length;
    vector<int> nums(length);
    for(int i = 0; i < length; i++){
        cin >> nums[i];
    }
    int left = 0;
    int right = 0;
    while(cin >> left >> right){
        int sum = 0;
        for(int j = left; j <= right; j++){
            sum += nums[j];
        }
        cout << sum << endl;
    }
    return 0;
    
}

第二种:了解“区间和”的用法,避免重复累加

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

int main(){
    int length = 0;
    cin >> length;
    vector<int> nums(length);
    vector<int> sums(length);
    int presum = 0;
    for(int i = 0; i < length; i++){
        scanf("%d", &nums[i]);
        //cin >> nums[i];
        presum += nums[i];
        sums[i] = presum;
    }
    int left = 0, right = 0;
    while(cin >> left >> right){
        if(left == 0){
            printf("%d\n", sums[right]);
            //cout << sums[right] << endl;
        }else{
            printf("%d\n", sums[right] - sums[left - 1]);
            //cout << sums[right] - sums[left - 1] << endl;
        }
    }
    return 0;
    
}

44.开发商购买土地

仍然要考虑“区间和”问题,避免重复计算

#include <iostream>
#include <vector>
#include <climits>
using namespace std;

int main(){
    int n,m;
    cin >> n >> m;
    vector<vector<int>> blocks(n, vector<int>(m, 0));
    int total = 0;
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            cin >> blocks[i][j];
            total += blocks[i][j];
        }
    }
    
    vector<int> horizen(n, 0);
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            horizen[i] += blocks[i][j];
        }
    }
    vector<int> vorizen(m, 0);
    for(int j = 0; j < m; j++){
        for(int i = 0; i < n; i++){
            vorizen[j] += blocks[i][j];
        }
    }
    int result = INT_MAX;
    //按行划分
    int horizen_sum = 0;
    for(int i = 0; i < n; i++){
        horizen_sum += horizen[i];
        result = min(result, abs(total - horizen_sum - horizen_sum));
    }
    //按列划分
    int vorizen_sum = 0;
    for(int j = 0; j < m; j++){
        vorizen_sum += vorizen[j];
        result = min(result, abs(total - vorizen_sum - vorizen_sum));
    }
    cout << result << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值