分治算法:把一个规模较大的复杂问题拆分成一些规模较小的问题,规模较小的问题继续拆分,直到这个问题变得不复杂,能解决为止。

分治算法解决的一些问题:二分搜索

                                          大整数乘法

                                         合并排序

                                         快速排序

                                         线性时间排序

                                         最大子数组

详细分析最大子数组:最大子数组有两种解决方法,1:暴力求解。2:用分治算法.

暴力求解:直接用循环把数组的所有子数组组合出来,算出所有子数组的和,比较大小,得到最大的子数组和。

分治算法解:最大子数组问题用分治算法分解,设最大子数组的开始下标为i,结束下标为j,把数组平分成两部分[0,mid]和[mid+1,length],i  和j可能在前半部分,也有可能在后半部分,也有可能i在前半部分,j在后半部分,分成这三个部分考虑,如果在前半部分求他的最大子数组,还可以用这个思想把前半部分的数组拆成两个,在讨论,数组一直可以继续拆,直到数组只剩两个数,两个数是分类讨论的最小情况了,这个时候问题也变得十分简单了,就可以求出最大子数组了。

最大子数组问题一般是由一些具体问题归成的,比如计算售卖商品,那上面的为例,你求价格的最大子数组是没有任何意义的,算出他们的变化的最大子数组是有具体意义的,可以得到他们在哪一段时间出售挣得最多。像股票等,都是这么分析的,得到他们变化值的最大子数组才有意义。

             

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Maxarray
{
    class Program
    {
        /// <summary>
        /// 用一个结构体存储最大字数组的值,和他在数组中的开始下标和结束下标
        /// </summary>
        struct MaxArray
        {
            public int value;
            public int LowIndex;
            public int HighIndex;

        }
        static void Main(string[] args)
        {
            List<int> arraylist = new List<int> { 100,113,110,85,105,102,86,63,81,101,94,106,101,79,94,90,97};//实际问题的数组值
            int[] pf = new int[arraylist.Count-1];
            for (int i = 0; i < arraylist.Count-1; i++)//算出每一天较前一天的的变化值,以便直关的显示每一天的盈亏情况
            {
                pf[i] = arraylist[i + 1] - arraylist[i];
            }

            MaxArray max=   maxSonAaary(0, pf.Length-1, pf);
            Console.WriteLine(max.value);//得到最大子数组的总和
            Console.WriteLine("最大子数组是从下表为{0}到下标为{1}",max.LowIndex,max.HighIndex);
            Console.ReadKey();
        }
        /// <summary>
        /// 采用分治算法将数组拆分成许多小数组,不断拆分,拆成最小的数组,进行计算,具体实现使用回调函数。
        /// </summary>
        /// <param name="low"></param>
        /// <param name="high"></param>
        /// <param name="array"></param>
        /// <returns></returns>
        static  MaxArray maxSonAaary(int low,int high,int[] array)
        {
            if(low==high)//拆成一个数组只有一个值时,停止分解
            {
                MaxArray arrayMax;
                arrayMax.value = array[low];
                arrayMax.LowIndex = low;
                arrayMax.HighIndex = high;
                return arrayMax;
            }
         int mid = (low + high) / 2;
         MaxArray arrayMax1=   maxSonAaary(low, mid, array);
         MaxArray arrayMax2=   maxSonAaary(mid + 1, high, array);
         MaxArray arrayMax3=new MaxArray();
            arrayMax3.LowIndex = mid;
            arrayMax3.HighIndex = mid + 1;
          int ArraySum = 0;
          int total = array[mid];
            for (int i = mid; i >=low; i--)
            {
                ArraySum += array[i];
                if(ArraySum>total)
                {
                    total=ArraySum;
                    arrayMax3.LowIndex = i;
                }
            }
            int total1 = array[mid + 1];
            int ArraySum1 = 0;
           
            for (int i = mid+1; i <= high; i++)
            {
                ArraySum1 += array[i];
                if(ArraySum1>total1)

                {
                    total1 = ArraySum1;
                    arrayMax3.HighIndex = i;
                }
            }
          arrayMax3.value = total+total1;
          if(arrayMax1.value>=arrayMax2.value&&arrayMax1.value>=arrayMax3.value)
            {
                return arrayMax1;
            }
          else if(arrayMax2.value>=arrayMax1.value&&arrayMax2.value>=arrayMax3.value)
            {
                return arrayMax2;
            }
            else
            {
                return arrayMax3;
            }

        }
    }
}

 

       暴力求解最大子数组

                   

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MaxArray
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] array = new int[] { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };
            int[] SonArray = new int[array.Length - 1];
            for (int i = 0; i < SonArray.Length; i++)//以前一天为标准,算出那些天是较前一天是增加还是减少
            {
                SonArray[i] = array[i + 1] - array[i];
            }
            int MinIndex;
            int MaxIndex;
            int MaxValue=  MaxSonArray(out MinIndex,out MaxIndex,SonArray);
            Console.WriteLine("最大子数组值{0},成员从{1}到{2}",MaxValue,MinIndex+1,MaxIndex+1);
            Console.ReadKey();


        }
        /// <summary>
        /// 暴力求解出数组的最大子数组
        /// </summary>
        /// <param name="MinIndex"></param>
        /// <param name="MaxIndex"></param>
        /// <param name="array"></param>
        /// <returns></returns>
        public static int MaxSonArray(out int MinIndex,out int MaxIndex,int[] array)
        {
            MinIndex = 0;
            MaxIndex = 0;
            int MaxValue = 0;
            for (int i = 0; i < array.Length; i++)
            {
                int tempValue = 0;
                for (int j=i;j<array.Length;j++)
                {
                    tempValue += array[j];
                    if(MaxValue<tempValue)
                    {
                        MaxValue = tempValue;
                        MinIndex = i;
                        MaxIndex = j;
                    }
                }
            }
            return MaxValue;
        }
    }
}

 

posted on 2019-07-31 16:13  晴耕--雨读  阅读(138)  评论(0编辑  收藏  举报