862,和至少为k的最短子数组

题目描述:

返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。

如果没有和至少为 K 的非空子数组,返回 -1 。

示例 1:

输入:A = [1], K = 1
输出:1
示例 2:

输入:A = [1,2], K = 4
输出:-1
示例 3:

输入:A = [2,-1,2], K = 3
输出:3

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-subarray-with-sum-at-least-k
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码

#include<iostream>
#include<stack>
#include<queue>
#include<deque>

using namespace std;

class Solution {
public:

    int shortestS(vector<int> &nums, int K)
    {
            nums.insert(nums.begin(),0);
            deque<int> dq;
            //nums[0]=0;
            // 前缀和
            for(int i=1;i<nums.size();i++){
                nums[i]=nums[i-1]+nums[i];
            }
            dq.push_front(0);
            //minv=n+1
            int minv=nums.size();
            //cout<<minv<<endl;
            for(int i=1;i<nums.size();i++){
                    /*保持栈中单调
                    *没有当前i的位置近而且比i的值大,因此右端点所需要的左端点肯定要将其舍弃
                    *前边的端点如果需要的,此时已经利用其更新了minv
                    *之所以不会将比i处值小的出栈,是因为还会因为他的值小会用到。
                    *过河拆桥,逐步添加,逐步舍弃大而远的元素
                    */
                while(!dq.empty()&&nums[i]<nums[dq.front()])
                    dq.pop_front();
                while(!dq.empty()&&nums[i]-nums[dq.back()]>=K)
                {
                    minv=min(minv,i-dq.back());
                    //cout<<minv<<endl;
                    dq.pop_back();
                }
                dq.push_front(i);
            }
            return minv==nums.size()?-1:minv;
    }
};

int main()

{

    vector<int> A;

    int n,data,k;

    cin>>n;

    for(int i=0; i<n; i++)

    {

        cin>>data;

        A.push_back(data);

    }

    cin>>k;

    int result=Solution().shortestS(A,k);

    cout<<result<<endl;

    return 0;

}

技巧理解

1,前缀和

类似于动态规划不需要每次计算区间的和,很容易获得差值,在这不用将所有元素保留在队列中,只需要保留对应元素下标即可,为单调队列做准备。

2,单调队列

加入队列中的元素不单调,0 2 4下标对应元素分别为0 4 3,4的值比3大,而且下标远离于后续需要判断的元素,因此直接被淘汰了。如果前边用到了4这个元素,也已经更新minv,因此直接舍弃。

3,舍弃队列中元素

如果添加顺序下标为0 2 4(元素值单调),则需要从4 2 0依次判断是否大于当前元素,然后直接出队。如果从0 2 4 顺序判断,则没办法利用队列的特性出队。

4,选择k最小对应的元素

应该也从0 2 4的顺序判断,如果0处的值符合,依然可以将其舍弃,后续逐步判断队列中其他元素。0处值符合了,已经的到了一个minv,后续元素如果用到肯定比当前minv大,因此可以舍弃。

5,每次加入当前元素

当前元素的优势在于靠近后续元素,而且前边已经保证了单调。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值