Leetcode No.53 Maximum Subarray(c++实现)
1. 题目
1.1 英文题目
given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
1.2 中文题目
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
1.3输入输出
输入 | 输出 |
---|---|
nums = [-2,1,-3,4,-1,2,1,-5,4] | 6 |
nums = [1] | 1 |
nums = [5,4,-1,7,8] | 23 |
1.4 约束条件
- 1 <= nums.length <= 3 * 104
- -105 <= nums[i] <= 105
2. 实验平台
ide:vs2019
ide版本:16.10.1
语言:c++11
3. 程序
3.1 测试程序
#include "solution.h" #include <vector> // std::vector #include<iostream> // std::cout using namespace std; // 主程序 void main() { // 输入 vector<int> nums = { -100000 }; solution solution; // 实例化solution int k = solution.maxsubarray(nums); // 主功能 // 输出 cout << k << endl; }
3.2 功能程序
3.2.1 穷举遍历法
(1)代码
#pragma once #include<vector> // std::vector using namespace std; //主功能 class solution { public: int maxsubarray(vector<int>& nums) { // 暴力求解 int maxvalue = -100000; for (int i = 0; i < nums.size(); i++) //遍历起始值 { int nowsub = 0; for (int j = i; j < nums.size(); j++) // 全部遍历一遍 { nowsub += nums[j]; if (nowsub > maxvalue) maxvalue = nowsub; } } return maxvalue; } };
(2)解读
该方法是最容易想到的方法,暴力求解,运用滑动窗口法进行遍历,分别得到以某个为开头的序列进行求最大值,并随遍历的进行实时更新该最大值。复杂度为o(\(n^2\))。
3.2.2 动态规划法
(1)代码
#pragma once #include<vector> // std::vector using namespace std; //主功能 class solution { public: int maxsubarray(vector<int>& nums) { // 动态规划(时间复杂度o(n),空间复杂度o(n)) int length = nums.size(); vector<int> dp(length); // 存储每次递归的最大值 dp[0] = nums[0]; for (int i = 1; i < length; i++) dp[i] = max(dp[i - 1] + nums[i], nums[i], [](int a, int b) {return a > b ? a : b; }); // lamda表达式 //求dp中的最大值 int maxsub = -100000; for (auto j : dp) // c++11中基于范围的for循环(range-based for loop) if (maxsub < j) dp[j] = maxsub; return maxsub; } };
(2)思路
参考:
3.2.3 kadane算法
(1)代码
#pragma once #include<vector> // std::vector using namespace std; //主功能 class solution { public: int maxsubarray(vector<int>& nums) { // kadane算法(时间复杂度o(n),空间复杂度o(1)) int length = nums.size(); int maxsub = nums[0]; // 慢指针 int maxsubtemp = nums[0]; //快指针 for (auto i : nums) { maxsubtemp = max(maxsubtemp + nums[i], nums[i], [](int a, int b) {return a > b ? a : b; }); // lamda表达式 if (maxsubtemp > maxsub) // 若当前最大值大于总最大值,则总最大值更新 maxsub = maxsubtemp; } return maxsub; } };
(2)解读
kadane算法是在动态规划法的基础上加上快慢指针法,快指针指向以i为结尾的子数组最大值之和,慢指针指向迄今为止的子数组最大值之和
3.3.4 分治法(divide and conquer)
(1)代码
pragma once
include // std::vector
//#include<limits.h> // int_min整型最小值
include // std::max
using namespace std;
//主功能
class solution {
public:
int maxsubarray(vector
if (nums.empty()) return 0;
return helper(nums, 0, (int)nums.size() - 1);
}
int helper(vector
{
if (left >= right) return nums[left];
int mid = left + (right - left) / 2;
int lmax = helper(nums, left, mid - 1);
int rmax = helper(nums, mid + 1, right);
int mmax = nums[mid], t = mmax;
for (int i = mid - 1; i >= left; --i)
{
t += nums[i];
mmax = max(mmax, t);
}
t = mmax;
for (int i = mid + 1; i <= right; ++i)
{
t += nums[i];
mmax = max(mmax, t);
}
return max(mmax, max(lmax, rmax));
}
};
参考:
(2)解读
参考:
4. 相关知识
(1)滑动窗口法
滑动窗口其实就是选取部分序列作为窗口,窗口不停移动,直至找到答案,感觉这更像一种思想。
详细介绍可以参考:
(2) lamda表达式
lamda表达式可以直接在需要调用函数的位置定义短小精悍的函数,而不需要预先定义好函数,但是不便于复用,适用于比较简单且不需要复用的函数。写法为:func(input1,input2,[],(type1 parameter1,type2 parameter2){函数;})
详细介绍参考:https://blog.csdn.net/a1138474382/article/details/111149792
(3) 基于范围的for循环(range-based for loop)
c++11中加入的新特性,类似于python,matlab等面向对象语言的for循环,写法为:for(auto i:array){;}
详细介绍参考:
(4)kadane算法
参考:
上一篇: 设计Person类 代码参考