day02-双指针-滑动窗口LeetCode习题

977. 有序数组的平方 - 力扣(LeetCode)

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

最简单的思路,就地将数组元素平方然后进行排序,但是时间复杂度是排序的时间复杂度这里用的是C++提供的快速排序,时间复杂度O(nlogn),空间复杂度O(1)

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        for(int i=0;i<nums.size();i++)
        {
            nums[i]*=nums[i];
        }
        sort(nums.begin(),nums.end());
        return nums;
    }
};

因为时间复杂度较高想要降低时间复杂度为O(n)级别,因为没有排序满足要求所以要换一个思路,这里选择用空间换时间引入一个结果集,因为如果元素是全是正数那么不需要排序,所以是负数元素影响了顺序,而负数越小那么平方越大所以只用比较最左边的元素平方和最右边元素平方的大小把大的放入结果集最后面即可这里可以容易地想到使用双指针

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int l=0,r=nums.size()-1;
        int k=r;
        vector<int> res(nums.size(),0);
        while(l<=r)
        {
            if(nums[l]*nums[l]<nums[r]*nums[r])
            {
                res[k]=nums[r]*nums[r];
                k--;
                r--;
            }
            else
            {
                res[k]=nums[l]*nums[l];
                k--;
                l++;
            }
        }
        return res;
    }
};

时间复杂度O(n),空间复杂度O(n)

209. 长度最小的子数组 - 力扣(LeetCode)

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

看到这道题最简单的思路一定就是暴力解法两重for循环,但是

  • 1 <= nums.length <= 105

length长度很大如果使用时间复杂度为O(n^2)的算法很显然要超时但是这里也提供一个暴力思路代码

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int length=INT_MAX;
        for(int i=0;i<nums.size();++i)
        {
            int sum=0;
            int l=0;
            bool flag=false;
            int x=i;
            while(sum<target&&x<nums.size())
            {
                sum+=nums[x];
                l++;
                x++;
                if(sum>=target)flag=true;
            }
            if(!flag)break;
            length=min(length,l);
        }
        if(length==INT_MAX)length=0;
        return length;
    }
};

时间复杂度 O(n^2) 空间复杂度O(1)

暴力解题不行就要想别的算法,其实我们暴力解法有很多重复的操作

最外层for循环每遍历一次我们就要从当前位置加到sum>=target的位置,那么有没有一种方法可以省略这些操作呢?

我们可以考虑最常用的方法用空间换时间,我们可以看作把增加的元素放入一个队列里面,当队列里面的元素综合大于等于目标数就可以把队头抛出,在队尾添加元素,直到再次大于等于,这就是滑动窗口法,但这里其实可以省略队列,只用sum表示即可

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int length=INT_MAX;
        int l;
        int sum=0;
        int j=0;//滑动窗口起始位置
        for(int i=0;i<nums.size();++i)
        {
            sum+=nums[i];
            while(sum>=target)
            {
                l=(i-j+1);
                length=min(length,l);
                sum-=nums[j];
                j++;//滑动窗口初始位置增加
            }
        }
        if(length==INT_MAX)length=0;
        return length;
    }
};

时间复杂度 O(n) 空间复杂度 O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

过客..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值