390,長度最小的子陣列

2021-10-09 17:53:07 字數 3349 閱讀 9624

給定乙個含有 n 個正整數的陣列和乙個正整數 s ,找出該陣列中滿足其和 ≥ s 的長度最小的連續子陣列,並返回其長度。如果不存在符合條件的連續子陣列,返回 0。

示例:

輸入: s = 7, nums = [2,3,1,2,4,3]

輸出: 2

解釋: 子陣列 [4,3] 是該條件下的長度最小的連續子陣列。

暴力求解首先這題最容易想到的是暴力求解,使用兩個for迴圈,乙個for迴圈固定乙個數字比如m,另乙個for迴圈從m的下乙個元素開始累加,當和大於等於s的時候終止內層迴圈,順便記錄下最小長度

public

intminsubarraylen

(int s,

int[

] nums)}}

return min == integer.max_value ?

0: min;

}

暴力求解雖然也能解出來,但畢竟效率很差,我們來看下其他的幾種解題方法

使用佇列(一)

實際上我們也可以把它稱作是滑動視窗,這裡的佇列其實就相當於乙個視窗。我們把陣列中的元素不停的入隊,直到總和大於等於s為止,接著記錄下佇列中元素的個數,然後再不停的出隊,直到佇列中元素的和小於s為止(如果不小於s,也要記錄下佇列中元素的個數,這個個數其實就是不小於s的連續子陣列長度,我們要記錄最小的即可)。接著再把陣列中的元素新增到佇列中……重複上面的操作,直到陣列中的元素全部使用完為止。

這裡以[2,3,1,2,4,3]舉例畫個圖來看下

上面畫的圖是使用佇列,但在**中我們不直接使用佇列,我們使用兩個指標,乙個指向隊頭乙個指向隊尾,和使用佇列類似,我們來看下**

public

intminsubarraylen

(int s,

int[

] nums)

}return min == integer.max_value ?

0: min;

}

使用佇列(二)上面使用的是相加的方式,也就是說佇列中(或者是視窗中)的元素相加,然後判斷是否大於等於s。其實我們還可以改為相減的方式,判斷s是否小於等於0,其實基本原理和上面差不多,我們來看下

public

intminsubarraylen

(int s,

int[

] nums)

}return min == integer.max_value ?

0: min;

}

二分法查詢我們還可以申請乙個臨時陣列sums,其中sums[i]表示的是原陣列nums中前i個元素的和,題中說了「給定乙個含有 n 個正整數的陣列」,既然是正整數,那麼相加的和會越來越大,也就是sums陣列中的元素是遞增的。我們只需要找到sums[k]-sums[j]>=s,那麼k-j就是滿足的連續子陣列,但不一定是最小的,所以我們要繼續找,直到找到最小的為止。

怎麼找呢,我們可以使用兩個for迴圈來列舉,但這又和第一種暴力求解一樣了,所以我們可以換種思路,求sums[k]-sums[j]>=s我們可以求sums[j]+s<=sums[k],那這樣就好辦了,因為陣列sums中的元素是遞增的,也就是排序的,我們只需要求出sum[j]+s的值,然後使用二分法查詢即可找到這個k值。

public

intminsubarraylen

(int s,

int[

] nums)

for(

int i =

0; i <= length; i++)}

return min == integer.max_value ?

0: min;

}

注意這裡的查詢函式

arrays.binarysearch(sums, target);

如果找到就會返回值的下標,如果沒找到就會返回乙個負數,這個負數取反之後就是查詢的值應該在陣列中的位置

舉個例子,比如排序陣列[2,5,7,10,15,18,20]如果我們查詢18,因為陣列中有這個數,所以會返回18的下標5,如果我們查詢9,因為陣列中沒這個數,所以會返回-4(至於這個是怎麼得到的,大家可以看下原始碼,這裡不再過多展開討論),我們對他取反之後就是3,也就是說如果我們在陣列中新增乙個9,他在陣列的下標是3,也就是第4個位置(也可以這麼理解,只要取反之後不是陣列的長度,那麼他就是原陣列中第乙個比他大的值的下標)

直接使用視窗

上面第2種解法我們使用的是使用兩個指標,我們也可以把它看做是乙個視窗,每次往視窗中新增元素來判斷是否滿足。其實我們可以逆向思維,先固定乙個視窗大小比如leng,然後遍歷陣列,檢視在陣列中leng個元素的和是否有滿足的,如果沒有滿足的我們就擴大視窗的大小繼續查詢,如果有滿足的我們就記錄下視窗的大小leng,因為這個leng不一定是最小的,我們要縮小視窗的大小再繼續找……

public

intminsubarraylen

(int s,

int[

] nums)

else

lo = mid +1;

//沒找到就擴大視窗的大小

}return min;

}//size視窗的大小

長度最小的子陣列

方法 1 暴力 想法按照題目要求直接求。把所有可能的子陣列求和並更新 textans 直到我們找到最優子陣列且和滿足 text geq textsum s 演算法初始化 text textans int max 用變數 ii 從左到右遍歷陣列 用變數 jj 從當前元素到陣列尾部遍歷 將 ii 到 j...

長度最小的子陣列

給定乙個含有n個正整數的陣列和乙個正整數s 找出該陣列中滿足其和 s的長度最小的連續子陣列。如果不存在符合條件的連續子陣列,返回 0。示例 輸入 s 7,nums 2,3,1,2,4,3 輸出 2解釋 子陣列 4,3 是該條件下的長度最小的連續子陣列。高階 如果你已經完成了o n 時間複雜度的解法,...

長度最小的子陣列

問題 給定乙個含有 n 個正整數的陣列和乙個正整數 s 找出該陣列中滿足其和 s 的長度最小的連續子陣列。如果不存在符合條件的連續子陣列,返回 0。示例 輸入 s 7,nums 2,3,1,2,4,3 輸出 2 解釋 子陣列 4,3 是該條件下的長度最小的連續子陣列。分析 暴力法 求出每個子陣列的和...