Leetcode日常刷码(3)解决最大子数组问题(Java)

本文深入探讨了求解最大子数组和问题的三种方法:暴力破解、分治法及动态规划,通过实例讲解每种算法的实现过程,对比它们的时间复杂度,帮助读者理解并掌握高效算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6

问题解决思路:

小编为大家介绍三种处理此问题的办法:(具体的思路已经放在代码的注释中了,请大家细细阅读,不懂可以留言)

第一:暴力破解

第二:分治法

第三:动态规划 

代码实现:

package Algorithm;

public class Example3 {
	//暴力求解最大子数组和时间复杂度比较高
	public int Violentsolution(int[] array){
		int sum = -10000;//记录子数组的和
		int low;//记录子数组的底
		int high;//记录子数组的高
		String result;
		for (int i = 0; i < array.length; i++){//利用两层for循环遍历所有的子数组情况
			for (int j = i; j < array.length; j++){
				int arraysum = 0;//所遍历出来的子数组的和
				for (int k = i; k <= j; k++){//i肯定比j大,i和j就是子数组的上下界
					arraysum = arraysum + array[k];
				}
				if (arraysum > sum){
					sum = arraysum;
					low = i;
					high = j;
				}
				
			}
		}
		return sum;
		
	}
	//用来比较三个数的大小
	public int Max(int Maxleftsum,int Maxrightsum){
		int max = -999999;
		int MaxRLsum = Maxleftsum + Maxrightsum;
		if (max < Maxleftsum){
			max = Maxleftsum;
		}
		if (max < Maxrightsum){
			max = Maxrightsum;
		}
		if (max < MaxRLsum){
			max = MaxRLsum;
		}
		return max;
		
		
	}
	//分治法的实质就是将一个大问题分治为若干个独立的小问题,一般采用递归的思想
	public int Divideconquer(int[] array, int left, int right ){//利用分治法求解最大子数组问题
		if (left == right){//递归出口
			return array[left];
			
		}
		int center = (right + left) / 2;
		int Maxleftsum = Divideconquer(array, left, center);
		int Maxrightsum = Divideconquer(array, center+1, right);
		
		//计算左边子数组的值
		int MaxleftBsum = 0,LeftBsum = 0;
		for (int i = center; i >= left; i-- ){
			LeftBsum += array[i];
			if ( MaxleftBsum < LeftBsum){
				MaxleftBsum = LeftBsum;
			}
		}
		//计算右边子数组的值
		int MaxrightBsum = 0,RightBsum = 0;
		for (int j = center + 1; j <= right; j++){
			RightBsum += array[j];
			if ( MaxrightBsum > RightBsum){
				MaxrightBsum = RightBsum;
			}
		}
		
		return Max(Maxleftsum, Maxrightsum);
		
	}
	//动态规划解决最大子数组问题
	public int DP(int array[]) {
		int start = 0, end = 0;//初始化最大子数组的起始位置(在数组中的下标)
		int Maxarray; //最大子数组的值
		int[] dp = new int[array.length];//用于进行动态规划的记录
		
		dp[0] = array[0];//将第一个数初始化为记录的第一条
		Maxarray = dp[0];//将记录的第一条初始化为最大值
		int temp = 0;
		for (int i = 1; i < array.length; i++){
			if (dp[i-1] <= 0){//前面的值<0,直接丢掉
				dp[i] = array[i];
				temp = i;//记录起始位置
			}
			else{
				dp[i] = array[i] + dp[i-1];
			}
			if (dp[i] > Maxarray){//求解最大子数组的和,开始位置,结束位置
				Maxarray = dp[i];
				start = temp;
				end = i;
			}
		}
		return Maxarray;
		
		
	}
	

	public static void main(String[] args) {
		int[] array = {-6, -8, 2, 1, 3, 0, -1};
		Example3 object = new Example3();
		System.out.print(object.DP(array));
		
	}
}

总结:

动态规划也是一种分治思想(比如其状态转移方程就是一种分治),但与分治算法不同的是,分治算法是把原问题分解为若干个子问题,自顶向下求解子问题,合并子问题的解,从而得到原问题的解。动态规划也是把原始问题分解为若干个子问题,然后自底向上,先求解最小的子问题,把结果存在表格(这里的表格就是上面代码中的dp数组,请大家留意)中,在求解大的子问题时,直接从表格中查询小的子问题的解,避免重复计算,从而提高算法效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值