【每日一題】643. 子數組最大平均數 I

2021-03-02 每日算法題

各位題友大家好,今天是每日算法題公眾號堅持日更的第 11 天。今天力扣上的每日一題是第 643 題「子數組最大平均數 I」。可以通過每日一題的小程序查看題目詳情:

題目大意

給定 n 個整數,找出平均數最大且長度為 k 的連續子數組,並輸出該最大平均數。

示例

輸入:[1,12,-5,-6,50,3] , k = 4輸出:12.75解釋:最大平均數 (12-5-6+50)/4 = 51/4 = 12.75

數據範圍解題思路

首先需要區分兩個概念:子串(子數組)子序列。 這兩個名詞經常在題目中出現,非常有必要加以區分。子串sub-string(子數組 sub-array)是連續的,而子序列 subsequence 可以不連續。

方法一:preSum

今天題目讓求最大平均數,由於 k 是不變的,因此可以先求區間的最大和,然後再除以 k。

上周我在題解中已經說過,求區間的和可以用 preSum。preSum 方法還能快速計算指定區間段 i ~ j 的元素之和。它的計算方法是從左向右遍歷數組,當遍歷到數組的 i 位置時,preSum表示 i 位置左邊的元素之和。

假設數組長度為 N,我們定義一個長度為 N+1 的 preSum 數組,preSum[i] 表示該元素左邊所有元素之和(不包含當前元素)。然後遍歷一次數組,累加區間 [0, i) 範圍內的元素,可以得到 preSum 數組。代碼如下:

N = len(nums)
preSum = range(N + 1)
for i in range(N):
    preSum[i + 1] = preSum[i] + nums[i]
print(preSum)

利用 preSum 數組,可以在 O(1) 的時間內快速求出 nums  任意區間 [i, j] (兩端都包含) 的各元素之和。

sum(i, j) = preSum[i + 1] - preSum[j]

對於本題,可以先遍歷一次,求數組每個位置的 preSum,然後再遍歷一次,求長度為 k 的每個區間的最大和。最終除以 k 得到最大平均數。

preSum

使用 Python2 寫的代碼如下。

class Solution(object):
    def findMaxAverage(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: float
        """
        N = len(nums)
        preSum = range(N + 1)
        for i in range(N):
            preSum[i + 1] = preSum[i] + nums[i]
        largest = float("-inf")
        for i in range(k - 1, N):
            largest = max(preSum[i + 1] - preSum[i + 1 - k], res)
        return largest / float(k)

方法二:滑動窗口

題目也可以抽象成長度固定為 k 的滑動窗口。當每次窗口右移的時候,需要把右邊的新位置加到窗口中的中,把左邊被移除的位置從窗口的減掉。這樣窗口裡面所有元素的是準確的,我們求出最大的和,最終除以 k 得到最大平均數。

這個方法只用遍歷一次數組。

需要注意的是,需要根據 i 的位置,計算滑動窗口是否開始、是否要移除最左邊元素:

當 i >= k - 1 時,最左邊第一個滑動窗口內的元素剛好 k 個,開始計算滑動窗口的最大和。當 i >= k 時,為了固定窗口的元素是 k 個,每次移動時需要將 i - k 位置的元素移除。

使用 Python2 寫的代碼如下。

class Solution(object):
    def findMaxAverage(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: float
        """
        sums = 0
        largest = float('-inf')
        for i, num in enumerate(nums):
            sums += num
            if i >= k:
                sums -= nums[i - k]
            if i >= k - 1:
                largest = max(sums, largest)
        return largest / float(k)

刷題心得

今天的題目非常好,雖然是個 Easy 題目,但是讓我們練習了 preSum滑動窗口 兩種方法的最基本用法。

preSum 方法要注意定義的 preSum 是否包含當前元素;歡迎加入刷題群

目前已經近 2000 人加入了每日一題打卡群。加入方式是通過每日一題打卡網站。每天都會同步力扣每日一題,這是個互相幫助、互相監督的算法題打卡網站,其地址是 https://www.ojeveryday.com/

想加入千人刷題群的朋友,可以複製上面的連結到瀏覽器,然後在左側點擊「加入組織」,提交力扣個人主頁,即可進入刷題群。期待你早日加入。

也可點擊 「閱讀原文」,直接提交力扣個人主頁。

關於作者

我是本文的作者是負雪明燭,畢業於北京郵電大學,目前就職於阿里巴巴。堅持刷算法題 5 年,共計刷了 800 多道算法題。做過的每個算法題都在 CSDN 上寫題解博客,獲得好評無數,CSDN 的累計閱讀量已經 160萬 次!博客地址是:https://blog.csdn.net/fuxuemingzhu

每日算法題」公眾號是我維護的一個算法題解公眾號,主要講解算法題的解法,也會分享找工作的經驗。歡迎關注。

題目來源:643. 子數組最大平均數 I連結:https://leetcode-cn.com/problems/maximum-average-subarray-i

相關焦點

  • ​LeetCode刷題實戰152:乘積最大子數組
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !今天和大家聊的問題叫做 乘積最大子數組,我們先來看題面:https://leetcode-cn.com/problems/maximum-product-subarray/Given an integer array nums, find the contiguous subarray within an array (containing
  • 【算法】找出數組中和最大的子數組
    分治,顧名思義,就是把原問題分開多個子問題,一一解決,最後子問題的解合併就是原問題的解。光說概念沒什麼用,下面上例子(這是《算法導論》Java版中的講到的,借用一下),我就不結合日常,直接說問題:給定一個數組,找出數組中和最大的子數組(子數組表示在原數組中連續的一些元素)。看到這個問題,是不是第一感覺就是暴力解題:兩個for循環,一個個組合計算。
  • 詳解連續子數組的最大累乘之動態規劃解法
    這個題目,當然可以用窮舉所有子數組的方法,找出最大值,時間複雜度妥妥地為O(n^2),這顯然不是我們想要的。如何用DP降低到O(n)才是我們的目標,這才是算法的魅力所在,接下來,總結DP求解的思維過程。
  • LeetCode 例題精講 | 16 最大子數組和:子數組類問題的動態規劃技巧
    Maximum Subarray Sum 最大子數組和(Easy)給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。示例:輸入: [-2,1,-3,4,-1,2,1,-5,4],輸出: 6解釋: 連續子數組 [4,-1,2,1] 的和最大,為 6。
  • LeetCode:連續子數組的最大和
    輸入一個整型數組,數組中的一個或連續多個整數組成一個子數組。求所有子數組的和的最大值。
  • 給定一個int 數組,給出其中連續子序列的最大和(高頻面試題系列)
    題目:輸入一個整型數組,數組裡有正數也有負數。數組中一個或連續的多個整數組成一個子數組。求所有子數組的和的最大值。
  • 一文看懂《最大子序列和問題》(內含Java,Python,JS代碼)
    題目描述求取數組中最大連續子序列和,例如給定數組為 A = [1, 3, -2, 4, -5], 則最大連續子序列和為 6,即 1 + 3 +(-2)+ 4 = 6。去首先我們來明確一下題意。題目說的子數組是連續的題目只需要求和,不需要返回子數組的具體位置。數組中的元素是整數,但是可能是正數,負數和 0。
  • LeetCode刷題第三周【數組(簡單)】
    日期Oct.28 - Nov.03 2020(每日一題)Ps:本周我們接著上一周繼續刷數組,難度依舊是簡單,題目不再按順序,而是隨機挑選,下周開始會加深難度。隨著學校的開課,我會將平時上課的內容和筆記也整理成MK的格式上傳。
  • 每日一題:力扣85-最大矩形
    ❞力扣85-最大矩形一、原題題目1.1 題目  給定一個僅包含 0 和 1 、大小為 rows x cols 的二維二進位矩陣,找出只包含 1 的最大矩形,並返回其面積。84題-柱狀圖中最大的矩形可以比較容易的想到思路,我們可以一行一行的考慮最大的矩形,如圖所示。
  • LeetCode 題解 | 523. 連續的子數組和
    連續的子數組和(點擊文末閱讀原文查看題目)題目描述給定一個包含非負數的數組和一個目標整數 k,編寫一個函數來判斷該數組是否含有連續的子數組,其大小至少為 2,總和為 k 的倍數,即總和為 n*k,其中 n 也是一個整數。
  • Maximum Sum Circular Subarray 環形子數組的最大和
    (Formally, C[i]=A[i] when 0<=i<A.length, and C[i+A.length]=C[i] when i>=0.)Also, a subarray may only include each element of the fixed buffer A at most once.
  • 怎麼每日一題又是動歸
    分割數組的最大值410.今天的內容,或者說每日一題也是實在變態,一看到就直接翻翻答案找找思路這樣o(╥﹏╥)o,話不多說進入正題。今天的內容依然是動歸主題。題目與解法給定一個非負整數數組和一個整數 m,你需要將這個數組分成 m 個非空的連續子數組。
  • 【每日一題】(33題)面試官:你對圖論了解多少?(三)
    一、前言2020.12.23 立的 flag,每日一題,題目類型不限制,涉及到JavaScript,Node,Vue,React,瀏覽器,http,算法等領域。本文是:【每日一題】(33題)面試官:你對圖論了解多少?(三)每日一題前兩期:【每日一題】(32題)面試官:你對圖論了解多少?
  • 最大子序(附加變種)
    題目 難度-簡單給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素)
  • ​LeetCode刷題實戰53:最大子序和
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !題意給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。樣例輸入: [-2,1,-3,4,-1,2,1,-5,4]輸出: 6解釋: 連續子數組 [4,-1,2,1] 的和最大,為 6。
  • [每日一題]410. Split Array Largest Sum
    給定一個正整數數組nums, 將其分成m個子數組(子數組至少應該有一個元素),那麼每一次分的子數組中的元素求和,會有一個最大值,建設是sum。問題是求所有的分法中,sum最小的值是多少。題目中舉了一個例子。
  • [每日一題]154. Find Minimum in Rotated Sorted Array II
    求一個遞增的數組的最小元素的非常簡單,就是第一個元素就行了。這是一道非常典型的 二分法 類型的題目。如果沒有 Tag 提醒,一般很難想到二分法。因為原數組不是單調遞增的,而是局部單調的。這道題能提升我們對二分法的應用範圍的理解:局部單調的情況下也是可以使用二分法的。
  • LeetCode刷題指南(數組和矩陣)
    ,這裡也準備和大家分享他的LeetCode題解,於是我結合自己在進行刷題時做的分析和理解,按照題目類型進行劃分,形成本系列的LeetCode刷題指南。本題可以以 O(N) 的時間複雜度、O(1) 空間複雜度來求解。主要思想是通過交換數組元素,使得數組上的元素在正確的位置上。遍歷數組,如果第 i 位上的元素不是 i + 1,那麼一直交換第 i 位和 nums[i] - 1 位置上的元素。
  • 如何求二維數組的前綴和?
    這個概念其實很容易理解,即一個數組中,第 n 位存儲的是數組前 n 個數字的和。通過一個例子來進行說明會更清晰。題目描述:有一個長度為 N 的整數數組 A,要求返回一個新的數組 B,其中 B 的第 i 個數 B[i]是「原數組 A 前 i 項和」。
  • [每日一題]131. Palindrome Partitioning
    每日一題]162.Find Peak Element[每日一題]410. Split Array Largest Sum[每日一題]209. Minimum Size Subarray Sum[每日一題]240. Search a 2D Matrix II[每日一題]74.