C#分治算法解决最大子数组问题

136 阅读1分钟

问题场景: 已知一组股票数据,求哪一天买入哪一天卖出收益最大。

image.png

最大子数组问题(暴力解法)

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;
            }
        }
    }