C#算法—分治算法求解股票问题

分治策略是:

对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。

可使用分治法求解的一些经典问题

(1)二分搜索

(2)大整数乘法

(3)Strassen矩阵乘法

(4)棋盘覆盖

(5)合并排序

(6)快速排序

(7)线性时间选择

(8)最接近点对问题

(9)循环赛日程表

(10)汉诺塔

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

股票问题:                C#算法—分治算法求解股票问题_第1张图片

 (1)暴力求解

嵌套循环,遍历所有的子数组,找到最大的子数组,从13开始遍历,一直遍历到7,找到最大的子数组,再从-3开始遍历,找到最大子数组,最简单粗暴,耗费性能最高,最消耗时间。

/****************************************************
 *  功能:使用暴力求解股票价格购买问题
*****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    
    void Start()
    {
        Suanfa();
    }
    void Suanfa()
    {
        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++)
        {
            //取得以i为子数组起点的所有子数组
            for (int j = i; j < priceFluctuationArray.Length; j++)//以i开始以i结束
            {
                //由i,j就确定了一个子数组
                int totalTemp = 0;//临时最大子数组的和
                for (int k = i; k < j+1; k++)
                {
                    totalTemp += priceFluctuationArray[k];//当前子数组的和
                }
                if (totalTemp>total)//判断当前子数组的和是否大于总和
                {
                    total = totalTemp;//最大子数组的和
                    startIndex = i;//最大子数组的开始索引
                    endIndex = j;//最大子数组的结束索引
                }
            }
        }
        Debug.Log("startIndex:"+startIndex);
        Debug.Log("endIndex:"+endIndex);
        Debug.Log("购买日期是第"+startIndex+"天 出售日期是第"+(endIndex+1)+"天");
    }
}

(2)分治法

求low和high数组的最大子数组(区间)(和最大):

由low和high取得中间的mid索引,由最初的[low,high]区间得到[low,mid][mid+1,high]两个区间,

i为子数组的开始索引,j为子数组的结束索引:

  1. i j 同时位于低区间
  2. i j 同时位于高区间
  3. i 位于低区间,j位于高区间 

因为ij是由mid分隔的,分别取得在low mid里面的i值,mid high里面的j值

/****************************************************
 *  功能:使用分治法求解股票价格购买问题
*****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    struct SubArray//最大子数组的结构体
    {
        public int startIndex;
        public int endIndex;
        public int total;
    }
    void Start()
    {
        Suanfa();
    }
    void Suanfa()
    {
        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);
        Debug.Log("startIndex:"+subArray.startIndex);
        Debug.Log("endIndex:"+subArray.endIndex);
        Debug.Log("购买日期是第"+ subArray.startIndex+"天 出售日期是第" +(subArray.endIndex + 1)+"天");
    }
    static SubArray GetMaxSubArray(int low, int high, int[] array)//用来取得array这个数组从low到high之间的最大子数组
    {
        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);//高区间最大子数组
        //从[low,mid]找到最大子数组[i,mid]
        int total1 = array[mid];//最大子数组的和
        int startIndex = mid;//最大子数组的开始索引
        int totalTemp = 0;//临时的和
        for (int i = mid; i >=low; i--)//从mid向low遍历
        {
            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++)//从mid+1向high遍历
        {
            totalTemp += array[j];
            if (totalTemp>total2)
            {
                total2 = totalTemp;
                endIndex = j;
            }
        }
        SubArray subArray3;
        subArray3.startIndex = startIndex;
        subArray3.endIndex = endIndex;
        subArray3.total = total1 + total2;
        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;
        }
    }
}

你可能感兴趣的:(C#,算法,数据结构)