健身代餐低脂,鯊魚菲特 8 口味即食雞胸肉 100g × 7 袋 19.9 元
前言
清明假期馬上就要結束了,小熊給大家帶來一道筆試和麵試中與「動態規劃」相關的常考的簡單題,這道題被位元組、微軟、亞馬遜和蘋果等各大網際網路大廠作為筆試題。
這道題就是 Leetcode 的第 53 題-最大子序和,瞭解「動態規劃」的童鞋,在看到最大兩個字的時候,很容易就會想到用「動態規劃」去解答,因為涉及到「最優解」的問題,一般都可以通過動歸去做。本題小熊提供「動態規劃」的思路供大家參考,希望對大家有所幫助。
題目
解題思路
本題是一道典型的「動態規劃」的題,因此採用動態規劃的策略去解答。
「定義狀態」 dp[i]:以 nums[i]結尾(包含 nums[i])的連續子陣列的最大和。
「狀態轉移方程」 dp[i] = max(dp[i - 1] + nums[i], nums[i]),其中 i >= 1,當 dp[i - 1] < 0 時,拋棄當前的和最大的連續子陣列,從 nums[i] 開始,重新尋找和最大的連續子陣列,否則,將 nums[i] 加入到當前的和最大的連續子陣列。
「邊界條件」 dp[0] = nums[0]。
「舉慄」
以陣列 nums[i] = [-2,1,-3,4,-1,2,1,-5,4] 為例子,如下圖示。
從上圖可以看出:dp[0] = nums[0] = -1 < 0,由於當前的連續子陣列的最大和小於零,因此應該丟棄 num[0],從 nums[1] = 1 開始重新尋找和最大的連續子陣列。
尋找和最大的連續子陣列的完整動圖,如下所示:
由狀態轉移方程可知,dp[i] 只與 dp[i - 1] 和 nums[i] 相關,因此沒必要再去定義 dp,直接複用 nums 即可。
Show me the Code
「C++」
1 int maxSubArray(vector<int>& nums) { 2 int maxSum = nums[0]; 3 for (int i = 1; i < nums.size(); ++i) { 4 nums[i] = max(nums[i - 1], 0) + nums[i]; 5 maxSum = max(maxSum, nums[i]);View Code6 } 7 8 return maxSum; 9 }
「Java」
1 int maxSubArray(int[] nums) { 2 int maxSum = nums[0]; 3 for (int i = 1; i < nums.length; ++i) { 4 nums[i] = Math.max(nums[i - 1], 0) + nums[i]; 5 maxSum = Math.max(maxSum, nums[i]); 6 } 7 8 return maxSum; 9 }View Code
「Python3」
1 def maxSubArray(self, nums: List[int]) -> int: 2 for i in range(1, len(nums)): 3 nums[i] = max(nums[i - 1], 0) + nums[i] 4 5 return max(nums)View Code
「Golang」
1 func maxSubArray(nums []int) int { 2 maxSum := nums[0]; 3 for i := 1; i < len(nums); i++ { 4 if nums[i - 1] > 0 { 5 nums[i] += nums[i - 1] 6 } 7 8 if nums[i] > maxSum { 9 maxSum = nums[i] 10 } 11 } 12 13 return maxSum; 14 }View Code
「C」
1 int maxSubArray(int* nums, int numsSize){ 2 int maxSum = nums[0]; 3 for (int i = 1; i < numsSize; ++i) { 4 nums[i] = fmax(nums[i - 1] + nums[i], nums[i]); 5 maxSum = fmax(maxSum, nums[i]); 6 } 7 8 return maxSum; 9 }View Code
「複雜度分析」
時間複雜度:「O(n)」,其中 n 是陣列的長度,需要遍歷一遍陣列。
空間複雜度:「O(1)」,未開闢額外的儲存空間。