算法作业第十三周(leetcode)——862. Shortest Subarray with Sum at Least K

这道题是一道挺有意思的题,也有一点难度。下面给出题目地址:

https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/

这道题的大意是给定一个整数序列,求一个最短的连续非空的子序列,使它的和至少为K,返回它的长度。 

这道题是一道对数字序列操作的题,而且是求连续子序列的和的问题。这种题的一个很自然的处理方法就是将序列中第一个数到第i个数的和存成数组sum。这样,任何一个连续子序列就可以用数组中两个数的差求出来。但是,很显然,只有这样处理是不行的。通过暴力循环,我们可以看出算法复杂度为O(n^2),而数组长度最大为50000,并不能满足。

后来看了一下别人的算法。发现它用了一种很特别的处理方法,就是关注第r个数结尾的最短的子序列,然后遍历r。这种倒过来保存的方法似乎比较适合滑动窗口。在遍历r的时候,我们知道这个子序列是以r结尾的,所以我们要找到一个最大的开头j,使j到r的子序列的和大于k。然后我们维护一个双端队列,队列中保存子序列可能的开头序号。在这里,我们先要明确双端队列中的两个数当isum[j],那么选择j作为子序列开头肯定是更好的解。因为,子序列更短而且差值更大。所以队列中的序号i是递增的,它们对应的sum[i]也是递增的 。

我们每遍历一次r,就应该往队列中插入r-1,就是前一个数。可以比较队列末尾的数值不值得保留。就是对比是否sum[j]

下面给出实现代码(下面这个是用list实现双端队列的版本):

class Solution {
public:
    list slide;
    int shortestSubarray(vector& A, int K) {
        int i, last, ans = 100000, index;
        vector sum;
        sum.push_back(0);
        for(i=0; i=sum[i-1])
                    slide.pop_back();
                else
                    break;
            }
            slide.push_back(i-1);
            if(sum[i]::iterator it=slide.begin();it!=slide.end();)
            {
                index = *it;
                if(index=K)
                    ans = i - index;
                else
                    break;
                it++;
            }

        }
        if(ans == 100000)
            ans = -1;
        return ans;
    }
};

结果:

算法作业第十三周(leetcode)——862. Shortest Subarray with Sum at Least K_第1张图片 

滑动数组实现双端队列法:

int slide[50010];
class Solution {
public:
    int shortestSubarray(vector& A, int K) {
        int i, last, ans = 100000, index, fro = 0, bac = -1;
        vector sum;
        sum.push_back(0);
        for(i=0; i=sum[i-1])
                    bac--;
                else
                    break;
            }
            last = max(0, i - ans + 1);
            bac++;
            slide[bac] = i-1;
            if(sum[i]>sum[i-1])
            {
                int cnt = fro;
                while(cnt<=bac)
                {
                    index = slide[cnt];
                    if(index=K)
                        ans = i - index;
                    else
                        break;
                    cnt++;
                }
            }


        }
        if(ans == 100000)
            ans = -1;
        return ans;
    }
};

 

结果:

算法作业第十三周(leetcode)——862. Shortest Subarray with Sum at Least K_第2张图片

你可能感兴趣的:(算法作业第十三周(leetcode)——862. Shortest Subarray with Sum at Least K)