问题描述
一个含有n个元素的整数数组,数组元素可以是正数也可以是负数,数组中连续的一个或多个元素称为改数组的子数组,子数组所有元素之和称为子数组和,求一个整数数组子数组和的最大值。例如数组array={1,2,4,8,5,6,7},相差就是{ 1,2,4,-3,1,1}
最大子数组就是{1,2,4,8}
这里 以 int 类型 为例
有一组数{ 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };
/// <summary>
/// 暴力破解
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
public int[] MaxOutCome(int[] array)
{
int[] mins = new int[array.Length - 1];
int MaxIndex = 0;
int MinIndex = 0;
int Total = 0;
for (int i = 0; i <array.Length-1; i++)//最后一次不用 没得减
{
mins[i] = array[i + 1] - array[i];
}
for (int i = 0; i < mins.Length; i++)//遍历下 差 数组
{
for (int j = i; j < mins.Length; j++)//从i 到length 依次遍历 0~L 1~L ....L-1~L;
{
int temp = 0;
for (int k = i; k <=j; k++)// 从i 到 j 依次 累加 再 进行判断 和是否 比total 大 j也要加 进去
{
temp += mins[k];
}
if (temp>Total)
{
Total = temp;
MaxIndex = j;
MinIndex = i;
}
}
}
//遍历 结束 返回 下标
return new int[] { MinIndex, MaxIndex+1 };//卖出 那一天 要 加上1 得到 从Minindex 到MaxIndex +1 之间 最大最大数组是[MinIndex,MaxIndex]
}
- 时间复杂度是 立方阶
- 下面优化了一下 是平方阶
-
static void MaxSubArray(int[] array) { int[] minValueArray = new int[array.Length - 1]; for (int i = 0; i < array.Length-1; i++) { minValueArray[i] = array[i + 1] - array[i]; } int MaxValue = minValueArray[0]; int endInex=0; int maxIndex=0; for (int i = 0; i < minValueArray.Length; i++) { int temp =minValueArray[i]; for (int j =i+1; j < minValueArray.Length; j++) { temp += minValueArray[j]; if (temp> MaxValue) { maxIndex = i; MaxValue = temp; endInex = j; } } } Console.WriteLine(MaxValue + "开始位置:" + (maxIndex+1)+"结束位置:"+(endInex+1)); }
递归 分治法
假设有数组 array [min,max]
可以 用mid 进行 分区
min mid max
[min,max]
假设i是最大字数组的最小索引,j是最大索引
用 mid 进行分区
[min,mid] [mid+1,hight]
分成两区间
分3种情况 进行考虑
- 1. i j 都在 最小分区 [min,mid]
- 2. i j 都在 最大分区[mid+1,max];
- 3. i 在最小分区,j在 最大分区 [min,mid] 也是最坏情况
/// <summary>
/// 递归 分治
/// </summary>
/// <param name="low"></param>
/// <param name="high"></param>
/// <param name="array"></param>
/// <returns></returns>
public MaxSubArray MaxSubArray2(int low,int high,int[] array)
{
//结束 条件
if (low==high)
{
MaxSubArray maxSubArray;
maxSubArray.startIndex = low;
maxSubArray.endIndex = high;
maxSubArray.total = array[low];
return maxSubArray;
}
int mid = (low + high) / 2;//分区
MaxSubArray subArray1 = MaxSubArray2(low, mid, array);//左边的 情况1
MaxSubArray subArray2 = MaxSubArray2(mid+1,high, array);//右边的 情况2
// 情况3
// 左边 寻找
int total = array[low];
int startIndex = low;
int temp = 0;
for (int i = low; i <=mid; i++)
{
temp += array[i];
if (temp>total)
{
total = temp;
startIndex = i;
}
}
//右边 寻找
int total2 = array[mid + 1];
int endIndex = mid + 1;
temp = 0;
for (int i = mid+1; i <high; i++)
{
total2 += array[i];
if (temp>total2)
{
total2 = temp;
endIndex = i;
}
}
// 情况3
MaxSubArray SubArray3;
SubArray3.startIndex = startIndex;
SubArray3.endIndex = endIndex;
SubArray3.total = total + total2;
if (subArray1.total > subArray2.total && subArray1.total > SubArray3.total)
{
return subArray1;
}
else if (subArray2.total > subArray1.total&&subArray2.total>SubArray3.total)
{
return subArray2;
}
else
{
return SubArray3;
}
}
类似的 动态规划算法:
最大连续子数组 问题 :
最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
解决思路1,用一次for遍历 用一个值来存储最大值,一个用来存储当前计算结果值, 如果这个结果值为负值,就从把结果清空,重新从nums[i]开始。
public int MaxSerialArray( int[] nums)
{
int max=nums[0];//默认 第一个位置初始值
int tempMax=0;
for(int i=0;i<nums.Length;i++)
{
if(temMax<=0)
{
//如果最大值已经是负数了,就从当前数开始 计算
tempMax=nums[i];
}else
{
tempMax+=nums[i];
}
//负数直接不考虑,因为 一个负数 加上后,最小的肯定是以 这个负数为起始点,
// 这点 理解 挺重/要的
max=Mathf.Max(max,tempMax);
}
return max;
}
本文探讨了求解最大子数组和问题的多种算法,包括暴力破解、动态规划和递归分治法。通过实例展示了不同算法的时间复杂度及优化过程。

4807

被折叠的 条评论
为什么被折叠?



