分治算法的应用及理解

文章介绍了如何运用分治策略来解决寻找给定数组中最大子数组和的问题,具体是通过C#编程实现。在分治算法的核心部分,它将问题分解为三类情况并递归地处理,最终找到最大子数组的起始和结束索引以及总和。文章以17天的股票价格为例,展示了如何将股票收益最大化的求解转化为最大子数组问题。
摘要由CSDN通过智能技术生成

分治法求解

  思路:在[low,high]区间取中间mid,将问题细化,变成了3种情况

  1. 最大子数组在[low,mid]区间;
  2. 最大子数组在[mid+1,high]区间;
  3. 最大子数组的起始在[low,mid]区间,终点在[mid+1,high]区间;

对于前2种,使用递归来查找,当找到low=mid(或mid+1=high),说明找到了

以上3种情况比较最大子数组的和,谁大即为所要的结果。

典型应用案例:

17天的股票,求哪天买入哪天卖出收益最大。(即求最大子数组问题)

天数

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

价格

100

113

110

85

105

102

86

63

81

101

94

106

101

79

94

90

97

变化

13

-3

-25

20

-3

-16

-23

18

20

-7

12

-5

-22

15

-4

7

该问题拟合成求最大子数组问题,及组成的数值和最大。

C#编程求解:

由于考虑到计算的结果得到的是包含起始买入时间,结束卖出时间和最大收益值三个变量,故此先定义一个结构体变量。

        struct SubArray
        {
            public int startIndex;
            public int endIndex;
            public int total;
        }

实现分治算法的灵魂核心算法

        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);
            //第3种情况
            //在[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;

            //比较三种大情况下的值
            if(subArray3.total>=subArray1.total && subArray3.total >= subArray2.total)
            {
                return subArray3;
            }
            else if(subArray2.total >= subArray1.total && subArray2.total >= subArray3.total)
            {
                return subArray2;
            }
            else
            {
                return subArray1;
            }
        }

在主函数中执行调用实现分治算法的方法(此处利用控制台环境实现)

 static void Main(string[] args)
        {

    int[] priceArray = { 100, 113, 110, 85, 105, 102, 96, 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("从第{0}天开始买入", subArray.startIndex);
            Console.WriteLine("从第{0}天进行卖出", subArray.endIndex + 1);
            Console.ReadKey();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值