如果解决上面的这个问题,采用分治法的话,可以把变化数组分为如下图的两段,两段会产生3中情况分别是:
1、最大子数组开始下标和结束下标都在【low,mid】范围内。
2、最大子数组开始下标和结束下标都在【mid+1,high】范围内。
3、最大子数组开始下标在mid前,结束下标在mid+1后。
相对于上面1 2两种情况采用递归方法。
分治法在每一层递归上都有三个步骤:
分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
合并:将各个子问题的解合并为原问题的解。
第3种就直接for查找在mid前的开始下标和mid+1后的结束下标,然后把两个计算和相加就好了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace _003最大指数组问题之分治法
{
class Program
{
struct SubArray
{
public int sumData;
public int startIndex;
public int endIndex;
}
static void Main(string[] args)
{
int[] priceArray = new int[] { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };
int[] changeArray = new int[priceArray.Length - 1];//变化
for (int i = 0; i < priceArray.Length - 1; i++)
{
changeArray[i] = priceArray[i + 1] - priceArray[i];//相对于前一天的变化值
}
SubArray subArray = GetMaxSubArray(0, changeArray.Length - 1, changeArray);//获取最大子数组函数
Console.WriteLine(subArray.startIndex);
Console.WriteLine(subArray.endIndex);
Console.WriteLine(string.Format("购买日期是第{0}天,出售是第{1}天", subArray.startIndex, subArray.endIndex + 1));
Console.ReadKey();
}
/// <summary>
/// 获取最大子数组函数
/// </summary>
/// <param name="low">最小下标</param>
/// <param name="high">最大下标</param>
/// <param name="array">查询的数组</param>
/// <returns></returns>
static SubArray GetMaxSubArray(int low,int high,int[] array)
{
int mid = (low + high) / 2;//取中间值,方便分两边处理
if(low==high)//递归调用退出条件
{
SubArray subArray;
subArray.sumData = array[low];
subArray.startIndex = low;
subArray.endIndex = high;
return subArray;
}
SubArray subArray1 = GetMaxSubArray(low, mid, array);//startIndex startIndex 都在左边
SubArray subArray2 = GetMaxSubArray(mid+1, high, array);//startIndex startIndex 都在右边
//下面是 startIndex 在左边 endIndex 在右边
int sumData=array[low];
int startIndex=low;
int endIndex = 0;
int temp = 0;
for (int i = mid; i >= low; i--)
{
temp += array[i];
if (sumData < temp)
{
sumData = temp;
startIndex = i;
}
}
int sumData2 = array[mid + 1];
temp = 0;
for (int i = mid+1; i <high; i++)
{
temp += array[i];
if (sumData2 < temp)
{
sumData2 = temp;
endIndex = i;
}
}
//合并 (startIndex 在左边 endIndex 在右边)数据到subArray3
SubArray subArray3;
subArray3.endIndex = endIndex;
subArray3.startIndex = startIndex;
subArray3.sumData = sumData + sumData2;
//那个总和大 返回那个
if(subArray1.sumData>=subArray2.sumData&&subArray1.sumData>=subArray3.sumData)
{
return subArray1;
}
else if (subArray2.sumData >= subArray1.sumData && subArray2.sumData >= subArray3.sumData)
{
return subArray2;
}
else
{
return subArray3;
}
}
}
}
经典问题
(1)二分搜索
(2)大整数乘法
(3)Strassen矩阵乘法
(4)棋盘覆盖
(5)合并排序
(6)快速排序
(7)线性时间选择
(8)最接近点对问题
(9)循环赛日程表
(10)汉诺塔