2021-03-31:給定一個數組arr,給定一個值v。求子數組平均值小於等於v的最長子數組長度。java
福大大 答案2021-03-31:git
這道題是昨天每日一題的變種。數組每一個元素減v,而後求<=0的最長子數組長度。
1.前綴和+有序表。時間複雜度O(N*lgN)。無代碼。
2.滑動窗口。時間複雜度O(N)。這道題用天然智慧想不到,須要練敏感度。有代碼。
數組每一個元素減v。
minSum數組,最小累加和,以i開頭最小值。
minSumEnd數組,以i開頭最小值,右邊界在哪裏。
採用滑動窗口,右指針每次移動多位,左指針每次移動一位。
雖然用到了兩個for循環,可是右指針不回退,因此複雜度是O(N)。github
代碼用golang編寫。代碼以下:golang
package main import "fmt" //https://github.com/algorithmzuo/algorithmbasic2020/blob/master/src/class40/Code04_AvgLessEqualValueLongestSubarray.java func main() { arr := []int{1000, -10, 60, -60, 3, 1, -2, 1, 10} v := 5 ret := ways1(arr, v) fmt.Println(ret) } func ways1(arr []int, v int) int { arrLen := len(arr) if arrLen == 0 { return 0 } //數組的全部值都減掉平均值 for i := 0; i < arrLen; i++ { arr[i] -= v } //最小累加和數組 //最小累加和數組的右邊界 minSums := make([]int, arrLen) minSumEnds := make([]int, arrLen) minSums[arrLen-1] = arr[arrLen-1] minSumEnds[arrLen-1] = arrLen - 1 for i := arrLen - 2; i >= 0; i-- { if minSums[i+1] < 0 { minSums[i] = arr[i] + minSums[i+1] minSumEnds[i] = minSumEnds[i+1] } else { minSums[i] = arr[i] minSumEnds[i] = i } } R := 0 sum := 0 ans := 0 for L := 0; L < arrLen; L++ { //R循環右擴 for R < arrLen && sum+minSums[R] <= 0 { sum += minSums[R] R = minSumEnds[R] + 1 } //統計答案 ans = getMax(ans, R-L) //L右擴前,須要處理 if R > L { sum -= arr[L] } else { R = L + 1 } } //數組修改了,須要還原 for i := 0; i < arrLen; i++ { arr[i] += v } return ans } func getMax(a int, b int) int { if a > b { return a } else { return b } }
執行結果以下:數組