LeetCode 53. Maximum Subarray
来源:互联网 发布:世界营销网络地图 编辑:程序博客网 时间:2024/06/05 07:01
这道题的题意是给定一个数组,要求求出最大的连续子序列的和。
这道题有很多的做法,而我做的有四种,下面我按照时间复杂度从高到低说明一下这些算法。
(1) 最简单的做法是直接枚举左右端点,然后计算两个端点之间元素的和,枚举左右端点复杂度为O(n2),计算和的复杂度为O(n),总时间复杂度为O(n3)。实现比较简单,就
不给出代码。而O(n3)的时间复杂度不足以通过这道题。
(2)通过观察,我们可以发现上一种做法中的计算和的步骤是可以简化的。第二种做法可以先声明一个sum数组。sum[i] 表示原数组的元素0~i的和。计算的过程的时间复杂度
为O(n),有了这个数组,计算i~j的和只要用sum[j] - sum[i-1]即可,计算和的复杂度为O(1)。总的时间复杂度为O(n2),代码如下:
const int maxn = 1000000 + 20 ;int sum[maxn] ;# define INF 100000000 class Solution {public: int maxSubArray(vector<int>& nums) ;};int Solution::maxSubArray(vector<int>& nums) {memset(sum, 0, sizeof(sum)) ;vector<int> a ;a.push_back(0) ;int n = nums.size() ;for (int i=0; i<n; i++) a.push_back(nums[i]) ;sum[0] = 0 ;int ans = -INF ;for (int i=1; i<=n; i++) sum[i] = sum[i-1] + a[i] ;for (int i=1; i<=n; i++) {for (int j=0; j<i; j++) ans = max(sum[i]- sum[j], ans) ;}return ans ;}
但O(n2)的时间复杂度依然不足以通过这道题。
(3) 第三种方法用到了分治的思想。我们可以每次把数组分成两半,则有最大连续和的子序列有三种可能:1、左半边数组;2、右半边数组;3、左半边和右半边都有一部分
(需要连续)。因此我们可以写出一个递归的程序:当前序列的最大连续和等于左半边最大连续和、右半边最大连续和、还有通过中间的最大连续和。计算通过中间的最
大连续和的时间复杂度为O(n) (只要从中间向两边扫描即可)。则有推导公式,T(n) = T(n/2) + O(n),则时间复杂度O(nlogn),这样就能够通过这道题,代码如下:
const int maxn = 1000000 + 20 ;int sum[maxn] ;# define INF 100000000 class Solution {public: int maxSubArray(vector<int>& nums) ; int dfs(vector<int>& nums, int x, int y) ;};int Solution::maxSubArray(vector<int>& nums) {return dfs(nums, 0, nums.size() ) ;} int Solution::dfs(vector<int>& nums, int x, int y) {if (x >= y) return -INF ;if (x + 1 == y) return nums[x] ;int ans = -INF ;int m = x + (y-x)/2 ;ans = max(max(dfs(nums,x,m), dfs(nums,m,y)), ans) ;int L = nums[m-1], R = nums[m] ;int lv = 0, rv = 0 ;for (int i=m-1; i>=x; i--) {lv += nums[i] ; L = max(L, lv) ;}for (int i=m; i<y; i++) {rv += nums[i] ; R = max(R, rv) ;}ans = max(L+R, ans) ;//cout << x << " " << y << " " << ans << endl ;return ans ;}
(4)但O(nlogn)的做法并不是最快的。回到第二种做法,经过思考,我们可以发现第一维的枚举是不必要的,我们不需要枚举左端点,只要维护最小的左端点即可,而维护可
以在枚举右端点的过程中做到。这样时间复杂度就降到了O(n),代码如下:
const int maxn = 1000000 + 20 ;int sum[maxn] ;# define INF 100000000 class Solution {public: int maxSubArray(vector<int>& nums) ;};int Solution::maxSubArray(vector<int>& nums) {memset(sum, 0, sizeof(sum)) ;vector<int> a ;a.push_back(0) ;int n = nums.size() ;for (int i=0; i<n; i++) a.push_back(nums[i]) ;sum[0] = 0 ;int ans = -INF ;for (int i=1; i<=n; i++) sum[i] = sum[i-1] + a[i] ; int minsum = sum[0] ; for (int i=1; i<=n; i++) { ans = max(ans, sum[i] - minsum) ; minsum = min(minsum, sum[i]) ; }return ans ;}
- [LeetCode]53.Maximum Subarray
- LeetCode --- 53. Maximum Subarray
- [Leetcode] 53. Maximum Subarray
- [leetcode] 53.Maximum Subarray
- 【leetcode】53. Maximum Subarray
- [leetcode] 53.Maximum Subarray
- 【leetcode】53. Maximum Subarray
- LeetCode 53. Maximum Subarray
- [LeetCode]53. Maximum Subarray
- 53. Maximum Subarray LeetCode
- [LeetCode]53. Maximum Subarray
- leetcode 53. Maximum Subarray
- [leetcode] 53. Maximum Subarray
- LeetCode *** 53. Maximum Subarray
- 【LeetCode】53. Maximum Subarray
- leetcode 53. Maximum Subarray
- LeetCode 53. Maximum Subarray
- Leetcode:53. Maximum Subarray
- Struts2基础学习总结
- Android自定义View——刮刮卡效果
- Mysql忽略主键冲突,避免重复插入的几种方式
- linux chmod权限问题
- Java Thread.interrupt方法
- LeetCode 53. Maximum Subarray
- 什么是软件精灵?软件精灵功能介绍
- 三.统一异常处理器配置
- gulp前端自动化构建工具(四):gulp文件路径处理模块
- linux添加exFat支持
- 解决 Android N 7.0 上 报错:android.os.FileUriExposedException
- 搭建Android开发环境
- lua基本函数库
- Graphite简要教程