2021-03-30:給定一個整數組成的無序數組arr,值可能正、可能負、可能0。給定一個整數值K,

2021-03-30:給定一個整數組成的無序數組arr,值可能正、可能負、可能0。給定一個整數值K,找到arr的全部子數組裏,哪一個子數組的累加和<=K,而且是長度最大的。返回其長度。java

福大大 答案2021-03-30:git

1.前綴和+有序表。時間複雜度O(N*lgN)。無代碼。github

2.滑動窗口。時間複雜度O(N)。這道題用天然智慧想不到,須要練敏感度。有代碼。
minSum數組,最小累加和,以i開頭最小值。
minSumEnd數組,以i開頭最小值,右邊界在哪裏。
採用滑動窗口,右指針每次移動多位,左指針每次移動一位。
雖然用到了兩個for循環,可是右指針不回退,因此複雜度是O(N)。golang

代碼用golang編寫,代碼以下:數組

package main

import "fmt"

func main() {
    arr := []int{1000, -10, 60, -60, 3, 1, -2, 1, 10}
    k := 1
    ret := maxLengthAwesome(arr, k)
    fmt.Println(ret)

}
func maxLengthAwesome(arr []int, k int) int {
    if len(arr) == 0 {
        return 0
    }
    minSums := make([]int, len(arr))
    minSumEnds := make([]int, len(arr))
    minSums[len(arr)-1] = arr[len(arr)-1]
    minSumEnds[len(arr)-1] = len(arr) - 1
    for i := len(arr) - 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
        }
    }

    // 遲遲擴不進來那一起的開頭位置
    end := 0
    sum := 0
    ans := 0
    for i := 0; i < len(arr); i++ {
        // while循環結束以後:
        // 1) 若是以i開頭的狀況下,累加和<=k的最長子數組是arr[i..end-1],看看這個子數組長度能不能更新res;
        // 2) 若是以i開頭的狀況下,累加和<=k的最長子數組比arr[i..end-1]短,更新仍是不更新res都不會影響最終結果;
        for end < len(arr) && sum+minSums[end] <= k {
            sum += minSums[end]
            end = minSumEnds[end] + 1
        }
        ans = getMax(ans, end-i)
        if end > i { // 還有窗口,哪怕窗口沒有數字 [i~end) [4,4)
            sum -= arr[i]
        } else { // i == end,  即將 i++, i > end, 此時窗口概念維持不住了,因此end跟着i一塊兒走
            end = i + 1
        }
    }
    return ans
}

func maxLength(arr []int, k int) int {
    h := make([]int, len(arr)+1)
    sum := 0
    h[0] = sum
    for i := 0; i != len(arr); i++ {
        sum += arr[i]
        h[i+1] = getMax(sum, h[i])
    }
    sum = 0
    res := 0
    pre := 0
    llen := 0
    for i := 0; i != len(arr); i++ {
        sum += arr[i]
        pre = getLessIndex(h, sum-k)
        if pre != -1 {
            llen = i - pre + 1
        }
        res = getMax(res, llen)
    }
    return res
}
func getLessIndex(arr []int, num int) int {
    low := 0
    high := len(arr) - 1
    mid := 0
    res := -1
    for low <= high {
        mid = (low + high) / 2
        if arr[mid] >= num {
            res = mid
            high = mid - 1
        } else {
            low = mid + 1
        }
    }
    return res
}
func getMax(a int, b int) int {
    if a > b {
        return a
    } else {
        return b
    }
}

執行結果以下:
在這裏插入圖片描述ide


左神java代碼
評論指針

相關文章
相關標籤/搜索