2021-03-31:給定一個數組arr,給定一個值v。求子數組平均值小於等於v的最長子數組長度。

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
    }
}

執行結果以下:數組

圖片


左神java代碼
評論ide

相關文章
相關標籤/搜索