给定一个整数数组,找到一个具有最大和的子数组,返回其最大和

/**
     * 给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。
     * 样例
     * 给出数组[−2,2,−3,4,−1,2,1,−5,3],符合要求的子数组为[4,−1,2,1],其最大和为6
     * 
     * 分析:子数组是指原数组中连续的一组数。求最大值,如果数组中元素都小于0;则直接返回数组的最大值。对于一般的情况。我们只要遍历求数组,

           同时对其求和,如果和数变得小于0,那就说明了此时这个子数组是不符合题意的,如果和数为正且大于之前求和过程中记录的最大值,那就将这个

           和数赋值给MAX,这样遍历一趟就将其中的最大和给求出来了。
     *
     * @param args
     */

 

 

import java.util.ArrayList;
import java.util.List;

public class Snippet {
	
	/***
	 * @desc 
	 * 方法一:暴力枚举 
		定义一个最大值max初始化一个很小的数,定义一个变量sum表示求和值,遍历数组元素,从第一个元素开始,依次相加,
		如果和sum比最大值max大就将sum赋值给最大值。然后再来一个循环控制从第i个数组元素开始求和,直到n. 
		时间复杂度:O(n^2)
	 * @param params
	 * @return
	 */
	public static List<Integer> subArraySumItem(int[] params) {
	    int currentSum = 0;
	    int curStart = 0;
	    int maxSum = 0;
	    int start = 0;
	    int end = 0;
	    for (int i = 0; i < params.length; i++) {
	        currentSum += params[i];
	        if(currentSum > 0) {
	            if (currentSum > maxSum) {
	                maxSum = currentSum;
	                start = curStart ;
	                end = i;
	            }
	        }else{
	            currentSum = 0;
	            curStart = i ;//i=2
	            
	        }
	    }
	    List<Integer> list = new ArrayList<Integer>();
	    for (int i = start+1; i <=end ; i++) {
	        list.add(params[i]);
	    }
	    return list;
	}
	
	
	
	
	private static int getMaxSum(int[] arr) {
        int max = -100000;
        for (int i = 0; i < arr.length; i++) {
            int sum = 0;
            for (int j = i; j < arr.length; j++) {
                sum += arr[j];
                if (max < sum) {
                    max = sum;
                }
            }
        }

        return max;
    }
	
	/**
	 * 给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。
	 * 样例
	 * 给出数组[−2,2,−3,4,−1,2,1,−5,3],符合要求的子数组为[4,−1,2,1],其最大和为6
	 * 
	 * 分析:子数组是指原数组中连续的一组数。求最大值,如果数组中元素都小于0;则直接返回数组的最大值。对于一般的情况。我们只要遍历求数组,

	       同时对其求和,如果和数变得小于0,那就说明了此时这个子数组是不符合题意的,如果和数为正且大于之前求和过程中记录的最大值,那就将这个

	       和数赋值给MAX,这样遍历一趟就将其中的最大和给求出来了。
	 *
	 * @param args
	 */
	public static void main(String[] args) {
	    int[] arrays = new int[]{-2, 2, -3, 4, -1, 2, 1, -5, 3};
	   
	    /*List<Integer> list = subArraySumItem(arrays);
	    System.out.println("list=" + list);*/
	    
        int maxSum = getMaxSum(arrays);
        System.out.println("最大子数组的和为:" + maxSum);
	    
	    /*System.out.println("dd->" + getMaxSum2(arrays));*/
	  
	}

 

解法1:暴力枚举 通过枚举所有的连续子数组,计算它们的,最后返回最大。 时间复杂度:O(n^2) 代码: class Solution: def maxSubArray(self, nums: List[int]) -> int: max_sum = float('-inf') for i in range(len(nums)): cur_sum = 0 for j in range(i, len(nums)): cur_sum += nums[j] if cur_sum > max_sum: max_sum = cur_sum return max_sum 解法2:动态规划 我们可以用 dp[i] 表示以第 i 个元素结尾的最大连续子数组,那么 dp[i] 可以由 dp[i-1] 转移得到: dp[i] = max(dp[i-1] + nums[i], nums[i]) 时间复杂度:O(n) 代码: class Solution: def maxSubArray(self, nums: List[int]) -> int: dp = [0] * len(nums) dp[0] = nums[0] max_sum = nums[0] for i in range(1, len(nums)): dp[i] = max(dp[i-1] + nums[i], nums[i]) max_sum = max(max_sum, dp[i]) return max_sum 解法3:分治法 将数组分成左右两部分,分别求出左半部分的最大子数组、右半部分的最大子数组以及跨越中心的最大子数组,最后返回三者中的最大值。 时间复杂度:O(nlogn) 代码: class Solution: def maxSubArray(self, nums: List[int]) -> int: return self.helper(nums, 0, len(nums)-1) def helper(self, nums, left, right): if left > right: return float('-inf') mid = (left + right) // 2 left_max = self.helper(nums, left, mid-1) right_max = self.helper(nums, mid+1, right) cross_max = self.crossMax(nums, left, mid, right) return max(left_max, right_max, cross_max) def crossMax(self, nums, left, mid, right): left_max = float('-inf') cur_sum = 0 for i in range(mid, left-1, -1): cur_sum += nums[i] left_max = max(left_max, cur_sum) right_max = float('-inf') cur_sum = 0 for i in range(mid+1, right+1): cur_sum += nums[i] right_max = max(right_max, cur_sum) return left_max + right_max 解法4:贪心算法 我们可以从左到右遍历数组,记录当前连续子数组 cur_sum 最大连续子数组 max_sum,如果 cur_sum 加上下一个数 nums[i] 小于 nums[i],那么从 nums[i] 开始重新计算 cur_sum。每次更新 max_sum,最后返回 max_sum 即可。 时间复杂度:O(n) 代码: class Solution: def maxSubArray(self, nums: List[int]) -> int: cur_sum = max_sum = nums[0] for i in range(1, len(nums)): cur_sum = max(nums[i], cur_sum+nums[i]) max_sum = max(max_sum, cur_sum) return max_sum
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值