数据结构
本文的撰写得到了黑牛大船舶与海洋学院院长、博士生导师牛子豪教授的指导,特此致谢。
leetcode53
求N个整数的序列子列和最大值
方法一 暴力解法,利用三重循环
#include <stdlib.h>
#include <stdio.h>
int getSum1(int arr[], int n);
int main(){
int n;
int sum;
scanf("%d", &n);
int arr[n];
int i;
for(i=0 ;i<n; i++) {
arr[i] = rand() - rand();
printf("%d \n", arr[i]);
}
sum = getSum1(arr,n);
printf("%d", sum);
}
int getSum1(int arr[], int n){
int i, j, k, thisSum, maxSum=0;
for(i=0; i<n; i++){
for(j=i; j<n; j++){
thisSum = 0;
//当j发生改变时,就要进行新一轮运算,需要注意将变量thisSum清零
for(k=i; k<=j; k++) // i,j分别是子列的开头与结尾
{
thisSum += arr[k];
}
if(thisSum > maxSum)
maxSum = thisSum;
}
}
return maxSum;
}
注意:1.rand() 生成的是伪随机数,利用该函数需要引入头文件**<stdlib.h>**
2. 这个解法使用了三重循环
第一重循环的目的是改变子列的起始位置
第二重循环是根据i 确定子列的终止位置
第三重循环是根据锁定的起始和终止位置求和
方法二 优化暴力解法
int getSum2(int arr[], int n)
{
int i, j, thisSum, maxSum=0;
for(i=0; i<n; i++)
{
thisSum = 0; // 每次进入内层及时清除 thisSum 的值
for(j=i; j<n; j++)
{
thisSum += arr[j];
if(thisSum > maxSum)
maxSum = thisSum;
}
}
return maxSum;
}
采用了定一动一的方法
在外层循环先确定i,再在内层循环中改变j的值,通过j的右移改变子列长度,而每右移一次,就进行一次比较,留下较大值
方法三 分而治之 O(n*log(n))
时间复杂度计算如下
这个算法写起来较为复杂,且需要采用递归
int Partition(vector<int>& x, int left, int right){
if(left==right) return x[left];
else{
int n = right-left;
int leftmax,rightmax;
if(n==1){
leftmax = x[left];
rightmax = x[right];
}
else{
int mid = (left+right)/2;
int thisLeft = x[mid], thisRight = x[mid+1];
leftmax = x[mid];
for(int i=mid-1; i>=left; i--){
thisLeft += x[i];
if(thisLeft>leftmax)
leftmax = thisLeft;
}
rightmax = thisRight;
for(int i = mid+2; i<=right; i++){
thisRight += x[i];
if(thisRight>rightmax)
rightmax = thisRight;
}
}
int max1 = max(Partition(x,left,left+n/2 ),Partition(x,left+n/2+1,right));
int max2 = max(max1,leftmax+rightmax);
return max2;
}
}
class Solution {
public:
int maxSubArray(vector<int>& nums);
};
int Solution::maxSubArray(vector<int>& nums){
int n = nums.size();
return Partition(nums,0,n-1);
}
maxSubArray是主函数,接收参数为一个vector容器的引用,返回最大子序列和(相较于C语言,用vector代替array)
Partition是辅助函数,用二分来切割原来的数组
方法四 在线处理 O(n) = n
int getSum4(int arr[], int n){
int i;
int thisSum = 0, maxSum = 0;
for(i=0; i<n; i++){
thisSum += arr[i];
if(thisSum > maxSum){
maxSum = thisSum;
}
else if(thisSum<0)
thisSum = 0;
}
return maxSum;
}
从序列开始位置进行计算,只利用一层循环
当 thisSum 的值不断增加,maxSum的值也会更新;
而当子列遇到负数thisSum的值减小,maxSum的值则不会改变