862. Shortest Subarray with Sum at Least K

本文分享了解决LeetCode 862题的高效算法思路,重点介绍如何通过排除负数作为子序列起始点和优化搜索策略,实现O(N)时间复杂度的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       好久没有更新了,这几天主要对hard级别的题目做了一些,今天分享一下862题的解题思路,一般看到这种类型的题目,有两个反应,暴力遍历所有情况,然后选择出最好的,但是这种情况肯定是行不通的,效率是非常低的,而且这种采用加和形式的题目,如果前面加出来的结果不能被后面的计算步骤利用,那将不是一个比较好的结果,因此,在看了大神们的代码后,整理了一下思路。

        为了实现O(N)的时间复杂度,我们可以从两个点入手:

        第一,当出现负数的时候,该点一定不能作为子序列的起始点,因为不论当前的子序列的和是小于目标值还是大于目标值,该点都不能作为起始点。如果目前的和已经大于目标值,则该点后面的点一定符合条件(因为负数对和是有消极作用的),如果目前的数小于目标值,起始点要么是前面某个正数,要么是后面某个数值,所以,负数出现的点一定不能作为满足条件的子序列起始点。

     第二点,若此时找到了满足情况的点,left(起点),right(终点),此时,如果我们需要更小的满足条件的其他序列,就不能在使用这个left作为起点,因为如果往后出现更短的满足条件的子序列,起点一定在该点之后。

     以上两点是整个算法的核心所在,另外,我们首先用一个序列表示前几个元素的和,这样,任何子序列的和都能通过该序列的两个元素相减得到,方便整个操作,本人不习惯于用公式推到,如果语言描述上有不清楚的地方,请大家说明。

具体的代码见下:

class Solution {
public:
    int shortestSubarray(vector<int>& A, int K) {
        if (A.size() < 1) {
            return -1;
        }
        int length = -1;
        
        vector<int> allsum (A.size()+1, 0);
        
        for (int i=1; i<allsum.size(); ++i) {
            allsum[i] = allsum[i-1]+A[i-1];
        }
        
        deque<int> dp;
        
        for (int right=0; right < allsum.size(); ++right) {
            
            while (!dp.empty() && allsum[right] <= allsum[dp.back()]) {
                dp.pop_back();
            }
            
            while (!dp.empty() && allsum[right]-allsum[dp.front()] >= K) {
                int left = dp.front();
                dp.pop_front();
                if (length == -1) {
                    length = right-left;
                } else {
                    length = min(length, right-left);
                }
            }
            
            dp.push_back(right);    
        }
        return length;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值