腾讯50题精选
题目描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解题思路以及编程知识
- 暴力求解。暴力求解是很基本的一种解法。基本思路就是通过循环遍历一遍,用两个变量,一个记录最大的和,一个记录当前的和。时空复杂度貌似还不错…(时间复杂度o(n),空间复杂度o(l)
- 分治法。(类似二分法)。思路:将数组分为左右两部分,用递归求解方法分别求最大子序和,再将左右两部分和中间值nums[mid]进行整合,先将nums[mid]和左边部分进行整合,再和右边进行整合,用两个for循环;最终得到左半边最大子序和l,右半边最大子序和r,和num_max,这三个的最大值就是最后的答案。
- 动态规划求解。暴力法的优化。
Leetcode运行代码
- 暴力法
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==0) return NULL;
int max=nums[0];//存最大值
int sum=0;//求和
for(int i=0;i<nums.size();i++)
{
sum=0;
for(int j=i;j<nums.size();j++)
{
sum+=nums[j];
if(sum>max) max=sum;
}
}
return max;
}
};
- 动态规划
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size() == 0) return NULL;
int res = INT_MIN;
int sum = -1;
for(int i = 0; i < nums.size(); ++i)
{
sum = max(nums[i], sum + nums[i]);
res = max(sum, res);
}
return res;
}
};
- 分治法
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==0) return NULL;
return fenzhifa(nums,0,nums.size()-1);
}
int fenzhifa(vector<int>& nums,int left,int right)
{
if(left>right) return INT_MIN;
if(left==right) return nums[left];
int mid=(left+right)/2;
int l=fenzhifa(nums,0,mid-1);//求左半边最大子序和
int r=fenzhifa(nums,mid+1,right);//求右半边最大子序和
int t=nums[mid];
int max_num=nums[mid];
for(int i=mid-1;i>=left;i--)//整合左半部分
{
t+=nums[i];
max_num=max(max_num,t);
}
t=max_num;
for(int i=mid+1;i<=right;i++)//整合右半部分
{
t+=nums[i];
max_num=max(max_num,t);
}
return max(max(r,l),max_num);
}
};
注:此方法耗时较长,建议用动态规划比较快。