和至少為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

1 <= A.length <= 50000
-10 ^ 5 <= A[i] <= 10 ^ 5
1 <= K <= 10 ^ 9

 

 

這道題的關鍵在於我們要知道各個區間的和。從而來判斷哪個區間的和是滿足要求的。用暴利解法逐個判斷是可行的,但是耗費的時間太多。因為暴力解法其實做了很多重復的工作。那么為了節省重復的計算,有個方法就是保存數組的前綴和數組。也就是用一個數組sum來記錄各個區間的和。也就是

sum[i]=arr[0]+arr[1]+……+arr[i-1]。這里為了計算方便,增加了以為sum[0]=0。有了這個數組,就可以很方便的求解任意區間的和。

比如要求區間[4,6]的和,就可以用sum[6]-sum[4]。

 

那么接下來的工作就是要將sum數組中的各個求和值入隊列。

(1) 當區間[0,i]的值比[0,i-1]的值要大的時候,就直接進隊列。

(2) 當區間[0…i]的值比區間[0….i-1]還要小的時候,那么對於后面的位置,其實可以忽略掉i-1,因為sum[n]-sum[i] > sum[n]-sum[n-1]。也就是[i,n]區間的值比[i-1,n]的值要大,而且更短。因此i-1這個位置就可以被踢出隊列。

比如隊列里面的數值如下:0,1,3,5,4。由於4比5小,此時應該將5剔除出隊列,為什么呢,如果保留5在隊列里面,當后面一個數組比如7進隊列的時候,隊列數組變成0,1,3,5,4,7。 這個時候計算區間和7-5明顯比7-4要小。而且[5,7]的區間長度為2,[4,7]的區間長度為1。因此5沒有必要存在於隊列中。隊里中的值變為0,1,3,4,7

 

每次完成隊列插入的操作后,就要開始對隊列里面的區間進行計算了。

當隊列為0,1的時候,1-0<4 不滿足條件

當隊列為0,1,3的時候,3-1<4 不滿足條件

當隊列為0,1,3,5的時候,5-0>4 滿足條件,最小長度為3。0出隊列,隊列變為1,3,5 繼續比較5-1>4,最小長度為2,1出隊列,隊列變為3,5。

當隊列為3,4的時候(由於5比4小,因此出隊列), 4-3<4不滿足條件

當隊列為3,4,7的時候,7-3>=4,滿足條件,最小長度為2

 

代碼如下:

沒有采用隊列或者棧的結構,就用數組來存儲dquue,用dq_begin, dq_end, dq_size來分別表示數組的第一個,最后一個元素以及數組長度。

int shortestSubarray(int a[], int k, int len)

{

    int *dqueue;

    int *sum;

    int i,dq_begin,dq_end,dq_size,min_length,lengh;

    dqueue = (int *)malloc((len + 1) * sizeof(int));

    sum = (int *)malloc(len * sizeof(int));

    memset(sum, 0,len * sizeof(int));

    memset(dqueue, 0, (len + 1) * sizeof(int));

    dq_begin = 0;

    dq_end = -1;

    dq_size = 0;

    min_length = len+1;

    for (i = 1; i <= len; i++)

    {

        *(sum + i) = *(sum+i-1)+a[i-1];

    }

    for (i = 0; i <= len; i++)

    {

        if (i != 0)

        {

             while (dq_size > 0 && sum[dq_end] >= sum[i])

             {

                 dq_end -= 1;

dq_size -= 1;

             }

             while (dq_size > 0 && sum[i] - sum[dq_begin] >= k)

             {

                 lengh = i - dq_begin;

                 min_length = min_length >= lengh ? lengh : min_length;

                 dq_begin += 1;

                 dq_size -= 1;

             }

        }

        dq_end += 1;

        dqueue[dq_end] = i;

        dq_size += 1;

    }

    return min_length;

 

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM