分治算法-最大子数组问题

 

1.蛮力法求解

总体思路:

  蛮力法是最简单的实现方法,只要列出数组所有可能的组合,然后找出其中和最大的组合即可;

  蛮力法分三层循环实现:

    1)第一层循环用于固定子数组的起始位置;

    2)第二层循环用于确定子数组的结束位置;

    3)第三层循环用于子数组和的计算,从子数组的头开始遍历到其尾,累加起来就是该子数组的和。

 

实现:

   /// <summary>
        /// 暴力求解
        /// </summary>
        /// <param name="priceArray"></param>
        /// <param name="priceFlutuationsArray"></param>
        public static void Violentsolution(int[] priceArray,int[] priceFlutuationsArray)
        {
            int total = priceFlutuationsArray[0];//默认数组得第一个元素 是最大子数组
            int StartIndex = 0;
            int EndIndex = 0;

            for (int i = 0; i < priceFlutuationsArray.Length; i++)
            {
                //取得以i为子数组起点得 所有子数组
                for (int j = i; j < priceFlutuationsArray.Length; j++)
                {
                    //由i j就确定了一个子数组
                    int totalTemp = 0;//临时最大子数组得和
                    for (int k = i; k < j + 1; k++)
                    {
                        totalTemp += priceFlutuationsArray[k];
                    }
                    if (totalTemp > total)
                    {
                        total = totalTemp;
                        StartIndex = i;
                        EndIndex = j;
                    }
                }
            }
            Console.WriteLine("start:" + StartIndex);
            Console.WriteLine("End:" + EndIndex);
            Console.WriteLine("购买日期是第" + StartIndex + "天 出售日期是第" + (EndIndex + 1) + "");
            Console.WriteLine("total:" + total);
        
          }

 

2.分治法求解

总体思路:

  分治法的精髓:
    1)分--将问题分解为规模更小的子问题;
    2)治--将这些规模更小的子问题逐个击破;
    3)合--将已解决的子问题合并,最终得出“母”问题的解;
  所以原数组的最大子数组求法:
    1)分--将原数组拆分成两部分,每个部分再拆分成新的两部分......直到数组被分得只剩下一个元素;
    2)治--每个小型的数组找最大子数组,只有一个元素的数组,解就是该元素;
    3)合--将两个小型数组合并为一个数组,其中解有三种可能:
      • 左边的返回值大,
      • 右边的返回值大,
      • 中间存在一个更大的子数组和;
     返回值应选最大的;

实现:

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

namespace 最大子数组问题
{
    class Program
    {
        //最大子数组的结构体
        struct SubArray
        {
            public int startIndex;
            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[] pf = new int[priceArray.Length - 1];//价格波动的数组
            for (int i = 1; i < priceArray.Length; i++)
            {
                pf[i - 1] = priceArray[i] - priceArray[i - 1];
            }

            SubArray subArray = GetMaxSubArray(0, pf.Length - 1, pf);
            Console.WriteLine(subArray.startIndex);
            Console.WriteLine(subArray.endIndex);
            Console.WriteLine("我们在第" + subArray.startIndex + "天买入, 在第" + (subArray.endIndex + 1) + "天卖出");
            Console.ReadKey();
        }

        /// <summary>
        /// 这个方法用来取得array这个数组从low到high得最大子数组
        /// </summary>
        /// <param name="low"></param>
        /// <param name="high"></param>
        /// <param name="array"></param>
         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; //低区间[low,mid]  高区间[mid+1,high]

            SubArray subArray1= GetMaxSubArray(low, mid, array);

            SubArray subArray2=GetMaxSubArray(mid+1, high, array);

            SubArray subArray3 = GetMaxSub(low, mid, high, array);

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

        static SubArray GetMaxSub(int low,int mid,int high,int[] 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)
                {
                    total2 = totalTemp;
                    endIndex = j;
                }
            }
            SubArray subArray3;
            subArray3.startIndex = startIndex;
            subArray3.endIndex = endIndex;
            subArray3.total = total1 + total2;
            return subArray3;
        }
    }
}

 

posted @ 2018-01-02 15:19  RONGWEIJUN  阅读(2434)  评论(0编辑  收藏  举报