0862_和至少為K的最短子數組

來源:互聯網
上載者:User

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

Note:

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

暴力演算法

func shortestSubarray(A []int, K int) int {    minLen := 50001    tail := len(A) - 1    for i := 0; i <= tail; i++ {        sum := A[i]        if sum >= K {            minLen = 1            break        }        for j := i + 1; j <= tail; j++ {            sum += A[j]            if sum >= K {                l := j - i + 1                if l < minLen {                    minLen = l                }                break            }        }    }    if minLen != 50001 {        return minLen    }    return -1}

高效能版本演算法

func shortestSubarray(A []int, K int) int {    size := len(A)    sums := make([]int, size+1)    for i, n := range A {        if n >= K {            return 1        }        sums[i+1] = sums[i] + n    }    res := size + 1    //儲存0----i,有可能是合格最短子串的head    deque := make([]int, 0, 0)    for i := 0; i < size+1; i++ {        for len(deque) > 0 && (sums[i]-sums[deque[0]] >= K) {            // i 遞增            // 可能有 j>i 使得 sums[j] - sums[deque[0]] >= K            // 但是由於 j>i,所以deque[0]---i是以deque[0]作為頭的最短的合格子串            // 把 deque[0] 刪除            res = min(res, i-deque[0])            deque = deque[1:]        }        for len(deque) > 0 && (sums[i] <= sums[deque[len(deque)-1]]) {            // 如果存在 j>i>deque[r] 使得 sums[j] - sums[deque[r]] >= K            // 由於 sums[deque[r]] >= sums[i] 則            // sums[j] - sums[i] >= K 一定成立,並且 j-i < j-deque[r]            // 所以,以deque[r]作為頭,不可能是最短的符合條件子串,刪除            deque = deque[:len(deque)-1]        }        deque = append(deque, i)    }    if res == size+1 {        return -1    }    return res}

個人思路

  1. 相對於暴力破解,重複計算兩個元素之間的和,所以此處必須進行最佳化,只需要迴圈一遍數組,儲存0-i元素的和
  2. 假如a<b,sums[b]-sums[a]>=K,b-a則是子串長度
  3. deque(雙端隊列)儲存0-i,可能合格最短子串的head
  4. 遍曆sums,取deque的[0],判斷該元素作為子串的head,是否符合條件,如果符合條件,那麼它將是該數組元素作為head的合格子串中,最短的子串,從deque中剔除[0],減少後面的sums比次數
  5. 取deque的尾,值為r,sums[r]>=sums[i],那麼如果後面存在sums[j]-sums[r]>=k,那麼j>i>r,i->j之間的子串肯定也符合條件,並且更短,已r為head的子串,不可能是最短的欄位,在這裡可以刪除deque的這個尾,減少比對次數

總結

  • 在leetcode社區中,有Java版本的演算法代碼,思路和此處思路完全一致,但是時間效率比Golang版的搞,Golang版170ms左右,Java版本40+ms
  • 筆者經過對比代碼,主要區別在於deque這個儲存容器,在JDK中有對應的資料結構Deque雙端隊列,資料結構的插入效率導致的,筆者猜測Java中該結構用的雙向鏈表實現的,在插入元素過程中,不需要擴容,記憶體配置效率很高
  • Golang版本代碼,deque用的slice切片,在append過程中,不斷的擴容,進行記憶體配置,導致效率低
  • 有興趣的朋友可以在此處最佳化deque這個資料結構,採用struct對象,構建雙向鏈表結構,相信,效率和Java版本的應該差不多,在此,篇幅限制,雙向鏈表也不是該演算法的核心,筆者就到此為止
  • 資料結構作為資料的儲存容易,對演算法的影響也是巨大的

GitHub

  • 項目源碼在這裡
  • 筆者會一直維護該項目,對leetcode中的演算法題進行解決,並寫下自己的思路和見解,致力於人人都能看懂的演算法

個人公眾號

  • 喜歡的朋友可以關注,謝謝支援
  • 記錄90後碼農的學習與生活
image
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.