问题场景: 已知一组股票数据,求哪一天买入哪一天卖出收益最大。
最大子数组问题(暴力解法)
public 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[] priceFluctuationArray = new int[priceArray.Length-1];//价格波动的数组
//遍历求出价格波动数组的值
for (int i = 1; i < priceArray.Length; i++)
{
priceFluctuationArray[i - 1] = priceArray[i] - priceArray[i - 1];
}
int total = priceFluctuationArray[0];
int startIndex = 0;
int endIndex = 0;
for (int i = 0; i < priceFluctuationArray.Length; i++)
{
for (int j = i; j < priceFluctuationArray.Length; j++)
{
//两层循环后,由ij确定一个子数组
//通过循环,对子数组求和
int tempTotal = 0;
for (int k = i; k < j + 1; k++)
{
tempTotal += priceFluctuationArray[k];
}
//如果该子数组的值大于先前的total的值,更新total的值
//并记录startIndex和endIndex的值
if (tempTotal > total)
{
total = tempTotal;
startIndex = i;
endIndex = j;
}
}
}
Console.WriteLine("购买日期应为:第" + startIndex + "天");
Console.WriteLine("售出日期应为:第" + (endIndex+1) + "天");
}
最大子数组问题(分治算法)
internal class Program
{
//最大子数组结构体
internal struct SubArray
{
public int startIndex;
public int endIndex;
public int total;
}
public 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[] priceFluctuationArray = new int[priceArray.Length-1];//价格波动的数组
//遍历求出价格波动数组的值
for (int i = 1; i < priceArray.Length; i++)
{
priceFluctuationArray[i - 1] = priceArray[i] - priceArray[i - 1];
}
SubArray subArray = GetMaxSubArray(0, priceFluctuationArray.Length - 1, priceFluctuationArray);
Console.WriteLine(subArray.startIndex);
Console.WriteLine(subArray.endIndex);
}
public static SubArray GetMaxSubArray(int low,int high,int[] array)
{
if (low == high)
{
SubArray subArray;
subArray.startIndex = low;
subArray.endIndex = high;
subArray.total = array[low];
return subArray;
}
int mid = (low + high) / 2;
SubArray subArray1 = GetMaxSubArray(low, mid, array);
SubArray subArray2 = GetMaxSubArray(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,high]
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)
{
total2 = totalTemp;
endIndex = j;
}
}
SubArray subArray3;
subArray3.total = total1 + total2;
subArray3.startIndex = startIndex;
subArray3.endIndex = endIndex;
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;
}
}
}