LeetCode53最大子序和

题目

给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大。

例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4]
连续子序列 [4,-1,2,1] 的和最大,为 6

 

扩展练习:

若你已实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。


分析

一开始用的最简单最直接的方法,挨个的把每个子序列的和求一遍,时间复杂度O(n²),提交之后超时了。。。。。

嗯再换个方法,看了结题报告之后。。

第二种方法呢,动态规划。遍历一遍序列,从后向前遍历,每次加进去一个新的数字nums[i],比较nums[i]和nums[i]+上次循环得到的sum的和,谁比较大,令sum等于较大的数字,然后令maxSum = 较大的数字(maxSum同sum比较谁比较大)。时间复杂度O(n)。

第三种方法,分治算法,时间复杂度O(nlogn),递归找出左半部分的最大子序列和,递归找出右半部分最大子序列和。


代码:

//方法一
public static int maxSubArray1(int[] nums) {//超时
        int maxSum = nums[0];
        for (int i = nums.length - 1; i >= 0 ; i--) {
            int temp = 0;
            for (int j = i; j < nums.length; j++) {
                temp += nums[j];
                if (temp > maxSum)
                    maxSum = temp;
            }
        }
        return maxSum;
    }
//方法二
public static int maxSubArray2(int[] nums){
        int sum = nums[nums.length-1];
        int maxSum = sum;
        for (int i = nums.length - 2; i >= 0; i--) {
            sum = Math.max(nums[i] , nums[i] + sum);
            maxSum = Math.max(sum,maxSum);
        }
        return maxSum;
    }
//方法三
public static int maxSubArray(int[] nums){

        return searchMax(nums,0,nums.length-1);

    }

    public static int searchMax(int[] nums, int left, int right){

        if (left == right) return nums[left];

        int mid = (left + right)/2;

        int l = searchMax(nums, left, mid);
        int r = searchMax(nums, mid+1, right);

        int numsMid = nums[mid];
        for (int i = mid - 1, temp = numsMid; i >= left ; i--) {
            temp += nums[i];
            if (temp > numsMid) numsMid = temp;
        }
        for (int i = mid +1, temp = numsMid; i <= right; i++) {
            temp += nums[i];
            if (temp > numsMid) numsMid = temp;
        }

        if ( l >= r && l >= numsMid) return l;
        if ( r >= l && r >= numsMid) return r;
        return numsMid;


    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值