中级农民
- 积分
- 154
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2016-7-20
- 最后登录
- 1970-1-1
|
本帖最后由 alanyannick 于 2021-6-1 07:45 编辑
Easy #53. Maximum Subarray 最大子数组组合
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Example 2:
Input: nums = [1]
Output: 1
Solution:
找组合->DP or DivConq,其中暴力法都是穷举所有可能性的题,一般就可以就用DP来优化解决 or Divide&Conquer先分解成N个子问题然后merge得到最优解。
其中【暴力穷举的函数就是DP的状态转移方程】。因此,这类型的题一般都可以用DP,来用 【备忘录 or DP hash table】记录下之前算过的结果,空间换时间。然后,备忘录只需要【存储之前的两个状态】,做到【状态压缩】,就可以把O(N)的空间复杂度简化为(1)。子问题是相互独立的。
动态规划之所以比暴力算法快,是因为动态规划技巧【消除了重叠子问题】。
DP问题总结:
"计算机解决问题其实没有任何奇技淫巧,它唯一的解决办法就是穷举,穷举所有可能性。算法设计无非就是先思考“如何穷举”,然后再追求“如何聪明地穷举”。
1.列出动态转移方程,就是在解决“如何穷举”的问题。
之所以说它难,一是因为很多穷举需要递归实现,二是因为有的问题本身的解空间复杂,不那么容易穷举完整。
2.备忘录、DP table 就是在追求“如何聪明地穷举”。
用空间换时间的思路,是降低时间复杂度的不二法门"
【后续再系统刷类型题来总结。】
DP和Divide&Conquer的区别是:
分而治之:在子问题上做更多的工作,因此有更多的时间消耗。在分而治之中,【子问题彼此独立】。(比如二分)
动态编程:仅解决一次子问题,然后将其存储在表中。在动态编程中,【子问题不是独立的,是重叠子问题,大大优化运算效率】。
DP会记住重叠部分,从而获得优于“分而治之”的优势。
通常这两者都需要好好准备,因为有时候考官会想知道其他的解法:
Divide and conquer algorithms are a great way to evaluate your problem solving skills. Splitting problems into smaller subproblems (so that they can be solved easier) is one of the things that interviewers like to see in candidates. That’s why they love to ask dynamic programming problems or other algorithms such as binary search (which is an example of divide and conquer approach). It’s not about runtime or space efficiency, but more about your thought process.
Ideas:
这一题很明显,暴力解法就是通过for loop把所有可能性都穷举一遍。
因此状态转移方程其实就是:
1.每个subarray的子组合更新sub_max = max(current_value, current_value + sub_max)
2.找到sub_max,每次再和gloabal max更新。
- class Solution(object):
- def maxSubArray(self, nums):
- """
- :type nums: List[int]
- :rtype: int # 1.Brute force ideas
- # 2. DP, optimized from brute-force ideas, find the local_optimial, and stack them together to get the global_optimal
- # 3. Divide and Conquer: binary divide, find the local_optimimal, then stack them together to get the global_optimal
-
- @Note
- # check_later Algorithm @DP, @DFS/BFS, @Recurrive, @Greedy, @Divide&Conquer
- # Initialize our variables using the first element.
- current_array = max_array = nums[0]
-
- # Start with the 2nd element since we already used the first one.
- for value in nums[1:]:
- # update the max_array by max(max_array, current_array)
- # continuly sum them up
- # DP: sub_max => whole_max
-
- # Update the local optimal value by max (current_i, current_array+i)
- # Update the global optimal value
- current_array = max(value, current_array + value)
- max_array = max(max_array, current_array)
- # f(n) = f(n-1 {max_value|current_array} ) <-
- current_array <- f(n-2 {current_array|value})
- return max_array
复制代码
|
|