数据结构 leetcode

数据结构

本文的撰写得到了黑牛大船舶与海洋学院院长、博士生导师牛子豪教授的指导,特此致谢。

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的值则不会改变

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值