1. 分治算法
分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。可使用分治法求解的一些经典问题
(1)二分搜索
(2)大整数乘法
(3)Strassen矩阵乘法
(4)棋盘覆盖
(5)合并排序
(6)快速排序
(7)线性时间选择
(8)最接近点对问题
(9)循环赛日程表
(10)汉诺塔
2. 股票问题
3. 使用暴力求解求最大子数组
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _501_最大子数组
{
class Program
{
static void Main(string[] args)
{
//暴力求解
int[] priceArray = { 100,113,110,85,105,102,86,63,81,101,94,106,101,79,94,90,97};
//int[] dataArray = new int[] { 0, 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };
int[] dataArray = new int[priceArray.Length - 1];
//取得价格波动
for(int i=1;i<priceArray.Length;i++)
{
dataArray[i - 1] = priceArray[i] - priceArray[i - 1];
}
//1.
//int max = 0;
int ivalue = 0, jvalue = 0;
//List<int> sumList = new List<int>();
//for (int i = 0; i < dataArray.Length; i++)
//{
// int sum = dataArray[i];
// for (int j = i + 1; j < dataArray.Length; j++)
// {
// sum += dataArray[j];
// sumList.Add(sum);
// for (int k = 0; k < sumList.Count; k++)
// {
// if (sumList[k] > max)
// {
// max = sumList[k];
// ivalue = i;
// jvalue = j;
// }
// }
// }
//}
//2.
int max = dataArray[0];//默认第一个为最大;
for (int i = 0; i < dataArray.Length; i++)
{
//取得以i开始所有子数组
for (int j = i; j < dataArray.Length; j++)
{
int maxTemp = 0;//临时最大值
for (int index = i; index < j + 1; index++)
{
maxTemp += dataArray[index];
}
if (maxTemp > max)
{
max = maxTemp;
ivalue = i;
jvalue = j;
}
}
}
Console.WriteLine("max:" + " " + max + " " + "i:" + ivalue + " " +"j:"+jvalue);
Console.ReadKey();
}
}
}
4. 分治法求最大子数组
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _502_最大子数组_分治算法
{
class Program
{
struct SubArray
{
public int startInsex;
public int endIndex;
public int total;
}
static void Main(string[] args)
{
int[] priceArray = { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };
//int[] dataArray = new int[] { 0, 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };
int[] pf = new int[priceArray.Length - 1];
//取得价格波动
for (int i = 1; i < priceArray.Length; i++)
{
pf[i - 1] = priceArray[i] - priceArray[i - 1];
}
SubArray subArray = GetMaxArray(0, pf.Length - 1, pf);
Console.WriteLine(subArray.startInsex);
Console.WriteLine(subArray.endIndex);
Console.WriteLine("从" + subArray.startInsex + "天买入" + subArray.endIndex + "天卖出");
Console.ReadKey();
}
/// <summary>
/// 用来取得array这个数组从low到high之间的最大子数组
/// </summary>
/// <param name="low"></param>
/// <param name="high"></param>
/// <param name="array"></param>
static SubArray GetMaxArray(int low,int high,int[] array)
{
if(low==high)
{
SubArray subArray;
subArray.startInsex = low;
subArray.endIndex = high;
subArray.total = array[high];
return subArray;
}
int mid = (low + high) / 2;//低区间[low,mid] 高区间[mid+1,high]
SubArray subArray1 = GetMaxArray(low, mid, array);
SubArray subArray2 = GetMaxArray(mid + 1, high, array);
//从[low,mid]找到最大子数组[i,mid]
int total1 = array[mid];
int startIndex = mid;
int totalTemp = 0;
for(int i=mid;i>=low;i--)
{
totalTemp += array[i];
if(totalTemp>total1)
{
total1 = totalTemp;
startIndex = i;
}
}
//从[mid+1,high]找到最大子数组[mid+1,j]
int total2 = array[mid + 1];
int endIndex = mid + 1;
totalTemp = 0;
for(int j=mid+1;j<=high;j++)
{
totalTemp += array[j];
if(totalTemp>total2)
{
totalTemp = total2;
endIndex = j;
}
}
SubArray subArray3;
subArray3.startInsex = startIndex;
subArray3.endIndex = endIndex;
subArray3.total = total1 + 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;
}
}
}
}