代码随想录刷题day2|LeetCode209 长度最小的子数组、LeetCode59 螺旋矩阵II、KamaCoder58 区间和、KamaCoder44 开发商购买土地

209 长度最小的子数组

力扣题目链接

思考:

不断将子数组尾部延伸到元素和大于等于target,然后再缩小子数组头部。
当子数组元素和小于target或延伸到原数组最后一个元素但仍未满足target时该子数组不合法。


试着用双指针——滑动窗口法可在一个数组上操作,同时降低时间复杂度):

终结窗口指针遍历整个数组,起始窗口指针缩小合法窗口寻找长度最小的合法子串。      

我的代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int count=0,sum=0,result=INT32_MAX;
        for(int i=0,j=0;j<=nums.size()/*&&sum>=target*/;){
            if(sum<target&&j<nums.size()){
                sum+=nums[j];
                j++;
            }
            else if(sum>=target&&i<nums.size()){
                count=j-i;
                result=result<count?result:count;
                sum-=nums[i];
                i++;
                
            }
            if(j==nums.size()&&sum<target)
                    break;
        }
        return result<count?result:count;

    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

59 螺旋矩阵II

力扣题目链接

思考:联系二分查找学习到的循环不变量原则

这类题关键在于如何设置循环边界条件

当初刚学编程的时候就做过类似的矩阵题(好像是蛇形矩阵之类的,当时就很头疼...果然很久不写又卡了好久)

对于这题,要注意到顺时针填数矩阵有两层循环,内层循环是每转一圈有四条边,外层循环是有很多圈要转。为确保转某一圈时四条边长度相等,采取左闭右开的边端点取值比较合适。

以下图n=5和n=6为例,注意到转几圈和n有关,中央是否有空缺和n的奇偶性有关。

同时注意到每圈的边界在逐圈缩小,需要适当设置和增减内外边界的值。

我的代码:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        //坚持循环不变量原则,确定边界开闭后不改变
        //尝试左闭右开
        std::vector<vector<int>> matrix(n,vector<int>(n,0));
        int num=1,i=0,j=0;
        int loop=n/2;//循环一周(上下左右)次数和n的值有关——见例图
        int edgeout=n-1,edgein=0;//内外边界
        while(loop--){
            for(;j<edgeout;j++)//上边从左往右
                matrix[i][j]=num++;
            for(;i<edgeout;i++)//右边从上到下
                matrix[i][j]=num++;
            for(;j>edgein;j--)//下边从右往左
               matrix[i][j]=num++;
            for(;i>edgein;i--)//左边从下到上
                matrix[i][j]=num++;

            edgeout--;
            edgein++;
            i++;
            j++;
        }
        if(n % 2)//若n为奇数,则最中间会有一个元素需要单独填入
            matrix[i][j]=num;
        return matrix;
    }
};
  • 时间复杂度 O(n^2): 模拟遍历二维矩阵的时间
  • 空间复杂度 O(1)

KamaCoder58 区间和

卡码网题目链接

思考:一种很典型的数组类型题目 计算区间元素和

解决这类问题时,需要用到一个很有用的技巧:前缀和。

前缀和的思想是重复利用计算过的子数组之和,从而降低区间查询需要累加计算的次数。

前缀和法相比于暴力解法遍历数组求区间和,最大的优点是可以极大优化时间复杂度。

核心解法是设置一个前缀和(原数组下标从0到其他下标所在区间的元素和)数组sum,当要求某一个指定区间时,例如原数组下标2到下标5之间的区间和,可以通过sum[5]-sum[1]求得。

注意,在使用前缀和求解的时候要特别注意求解区间的选取。下标2到下标5之间的元素包括下标2的元素,所以减数是sum[1]而不是sum[2]。

(之后有空补个手绘图)

我的代码:

#include<iostream>
#include<vector>
using namespace std;
int main(){
    //使用前缀和数组来求指定区间和
    int n,a,b,result;
    int temp=0;
    cin>>n;
    std::vector<int> arr(n);
    std::vector<int> sum(n);
    //for(int i=0;i<n;i++)
    //时间超限的解决办法要考虑删除不必要循环
    for(int i=0;i<n;i++){
        //cin>>arr[i];
        //当处理的数据量很大时,使用scanf和printf函数会比cin和cout节省运行时间
        scanf("%d",&arr[i]);
        //temp=0;
       // for(int j=0;j<=i;j++)
        temp+=arr[i];
        sum[i]=temp;
        }
        
    while(scanf("%d%d",&a,&b)==2){//每当有一次输入流输入数据,循环执行一次
        //使用前缀和数组中的元素进行相减来求指定区间
        if(a==0)
            result=sum[b];
        else
            result=sum[b]-sum[a-1];
        printf("%d\n",result);
    }
    return 0;
}

*关于oj平台的判定,出现时间超限的问题时,要考虑减少不必要循环,并且当处理的数据量很大时,使用scanf和printf函数会比cin和cout节省运行时间。

KamaCoder44 开发商购买土地

卡码网题目链接

(没时间写这个题的博客了之后补上......嗯)

 *文章中学习到的解法来自代码随想录的B站视频(数组4~5)以及代码随想录的学习网站

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值