c#数据结构之最大子数组问题(分治法)

这里写图片描述
如果解决上面的这个问题,采用分治法的话,可以把变化数组分为如下图的两段,两段会产生3中情况分别是:
1、最大子数组开始下标和结束下标都在【low,mid】范围内。
2、最大子数组开始下标和结束下标都在【mid+1,high】范围内。
3、最大子数组开始下标在mid前,结束下标在mid+1后。
这里写图片描述

相对于上面1 2两种情况采用递归方法。
    分治法在每一层递归上都有三个步骤:
    分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
    解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
    合并:将各个子问题的解合并为原问题的解。
第3种就直接for查找在mid前的开始下标和mid+1后的结束下标,然后把两个计算和相加就好了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _003最大指数组问题之分治法
{
    class Program
    {
        struct SubArray
        {
            public int sumData;
            public int startIndex;
            public int endIndex;
        }
        static void Main(string[] args)
        {
            int[] priceArray = new int[] { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };
            int[] changeArray = new int[priceArray.Length - 1];//变化

            for (int i = 0; i < priceArray.Length - 1; i++)
            {
                changeArray[i] = priceArray[i + 1] - priceArray[i];//相对于前一天的变化值
            }

            SubArray subArray = GetMaxSubArray(0, changeArray.Length - 1, changeArray);//获取最大子数组函数

            Console.WriteLine(subArray.startIndex);
            Console.WriteLine(subArray.endIndex);
            Console.WriteLine(string.Format("购买日期是第{0}天,出售是第{1}天", subArray.startIndex, subArray.endIndex + 1));
            Console.ReadKey();
        }
        /// <summary>
        /// 获取最大子数组函数
        /// </summary>
        /// <param name="low">最小下标</param>
        /// <param name="high">最大下标</param>
        /// <param name="array">查询的数组</param>
        /// <returns></returns>
        static SubArray GetMaxSubArray(int low,int high,int[] array)
        {
            int mid = (low + high) / 2;//取中间值,方便分两边处理

            if(low==high)//递归调用退出条件
            {
                SubArray subArray;
                subArray.sumData = array[low];
                subArray.startIndex = low;
                subArray.endIndex = high;
                return subArray;
            }

            SubArray subArray1 = GetMaxSubArray(low, mid, array);//startIndex startIndex 都在左边
            SubArray subArray2 = GetMaxSubArray(mid+1, high, array);//startIndex startIndex 都在右边

            //下面是 startIndex 在左边  endIndex 在右边
            int sumData=array[low];
            int startIndex=low;
            int endIndex = 0;
            int temp = 0;
            for (int i = mid; i >= low; i--)
            {
                temp += array[i];
                if (sumData < temp)
                {
                    sumData = temp;
                    startIndex = i;
                }
            }
            int sumData2 = array[mid + 1];
            temp = 0;
            for (int i = mid+1; i <high; i++)
            {
                temp += array[i];
                if (sumData2 < temp)
                {
                    sumData2 = temp;
                    endIndex = i;
                }
            }

            //合并 (startIndex 在左边  endIndex 在右边)数据到subArray3
            SubArray subArray3;
            subArray3.endIndex = endIndex;
            subArray3.startIndex = startIndex;
            subArray3.sumData = sumData + sumData2;

            //那个总和大 返回那个
            if(subArray1.sumData>=subArray2.sumData&&subArray1.sumData>=subArray3.sumData)
            {
                return subArray1;
            }

            else  if (subArray2.sumData >= subArray1.sumData && subArray2.sumData >= subArray3.sumData)
            {
                return subArray2;
            }
            else
            {
                return subArray3;
            }
        }

    }
}

这里写图片描述

经典问题
(1)二分搜索
(2)大整数乘法
(3)Strassen矩阵乘法
(4)棋盘覆盖
(5)合并排序
(6)快速排序
(7)线性时间选择
(8)最接近点对问题
(9)循环赛日程表
(10)汉诺塔

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值