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

目录
  • 分治策略是:
  • 可使用分治法求解的一些经典问题
  • 分治算法 - 最大子数组问题
    • (1)暴力求解
    • (2)分治法
  • 分治法实现大数相乘 C#实现

分治策略是:

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

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

(1)二分搜索

(2)大整数乘法

(3)Strassen矩阵乘法

(4)棋盘覆盖

(5)合并排序

(6)快速排序

(7)线性时间选择

(8)最接近点对问题

(9)循环赛日程表

(10)汉诺塔

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

股票问题:

(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为子数组的结束索引:

  • i j 同时位于低区间
  • i j 同时位于高区间
  • 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#实现

用C#实现,尽可能的利用C#的特性。本例中,只要拆分的数字小于9位数,就可以直接相乘计算,保证不会溢出。

在编程中,还需要用的加法和减法,也要通过字符串模拟实现。

最终的乘法运算,依赖递归思想得以实现。

本文的代码还有一些可以优化的地方,比如对于不使用字符串而是全部使用数组,可能会更快点。

代码如下:

namespace bigIntMultiply
{
    class Program
    {
        static void Main(string[] args)
        {
           string a = "99999999999999";
           string b = "123456789001234567890";
            Stopwatch sw = new Stopwatch();
            sw.Start();
            string s = Multiply(b, b);
            sw.Stop();
            Console.WriteLine(s);
            Console.WriteLine(sw.Elapsed);
        }
        //字符串模拟乘法操作
        static string Multiply(string x, string y)
        {
            //deep++;// Console.WriteLine("-" + deep + "-");
            string negative = "";
            if ((x.StartsWith("-") && y.StartsWith("-")) || (!x.StartsWith("-") && !y.StartsWith("-")))
            {
                x = x.TrimStart('-'); y = y.TrimStart('-');
                negative = "";
            }
            else if ((x.StartsWith("-") && !y.StartsWith("-")) || (!x.StartsWith("-") && y.StartsWith("-")))
            {
                x = x.TrimStart('-'); y = y.TrimStart('-');
                negative = "-";
            }
            //如果长度都小于9,直接相乘,返回就行了。
            if (x.Length <= 9 && y.Length <= 9)
            {
                long tmp = (long.Parse(x) * long.Parse(y));
                if (tmp == 0)
                    return tmp.ToString();
                return negative + (long.Parse(x) * long.Parse(y)).ToString();
            }
            //公式里的abcd
            string a, b, c, d;
            if (x.Length <= 9)
            {
                a = "0"; b = x;
            }
            else
            {
                if (x.Length % 2 != 0)
                    x = "0" + x;
                a = x.Substring(0, x.Length / 2);
                b = x.Substring(x.Length / 2);
            }
            if (y.Length <= 9)
            {
                c = "0";
                d = y;
            }
            else
            {
                if (y.Length % 2 != 0)
                    y = "0" + y;
                c = y.Substring(0, y.Length / 2);
                d = y.Substring(y.Length / 2);
            }
            int n = x.Length >= y.Length ? x.Length : y.Length;
            string t1, t2, t3;
            //递归调用,根据公式计算出值。
            string ac = Multiply(a, c);
            string bd = Multiply(b, d);
            t1 = Multiply(Subtract(a, b), Subtract(d, c));
            t2 = Add(Add(t1, ac), bd);
            t3 = Add(Add(Power10(ac, n), Power10(t2, n / 2)), bd).TrimStart('0');
            if (t3 == "") return "0";
            return negative + t3;
        }
        //字符串模拟加法操作
        static string Add(string x, string y)
        {
            if (x.StartsWith("-") && !y.StartsWith("-"))
            {
                return Subtract(y, x.TrimStart('-'));
            }
            else if (!x.StartsWith("-") && y.StartsWith("-"))
            {
                return Subtract(x, y.TrimStart('-'));
            }
            else if (x.StartsWith("-") && y.StartsWith("-"))
            {
                return "-" + Add(x.TrimStart('-'), y.TrimStart('-'));
            }
            if (x.Length > y.Length)
            {
                y = y.PadLeft(x.Length, '0');
            }
            else
            {
                x = x.PadLeft(y.Length, '0');
            }
            int[] sum = new int[x.Length + 1];
            for (int i = x.Length - 1; i >= 0; i--)
            {
                int tmpsum = int.Parse(x[i].ToString()) + int.Parse(y[i].ToString()) + sum[i + 1];
                if (tmpsum >= 10)
                {
                    sum[i + 1] = tmpsum - 10;
                    sum[i] = 1;//表示进位
                }
                else
                {
                    sum[i + 1] = tmpsum;
                }
            }
            string returnvalue = string.Concat(sum);
            if (sum[0] == 1)
            {
                return returnvalue;
            }
            else
            {
                return returnvalue.Remove(0, 1);
            }
        }
        //字符串模拟减法操作
        static string Subtract(string x, string y)
        {
            //if (x.StartsWith("-") && !y.StartsWith("-"))
            //{
            //    return "-" + Add(x.TrimStart('-'), y);
            //}
            //if (y.StartsWith("-"))
            //{
            //    return Add(x, y.TrimStart('-'));
            //}
            //x是正数,y也是正数
            int flag = checkBigger(x, y);
            if (flag == 0)
            {
                return "0";
            }
            else if (flag == -1)
            {
                string tmp = y;
                y = x;
                x = tmp;
            }
            //保证了x>=y
            y = y.PadLeft(x.Length, '0');//y补0与x对齐
            int[] difference = new int[x.Length];
            for (int i = x.Length - 1; i >= 0; i--)
            {
                int tmpdifference;
                tmpdifference = int.Parse(x[i].ToString()) - int.Parse(y[i].ToString()) + difference[i];
                if (tmpdifference < 0)
                {
                    tmpdifference += 10;
                    difference[i - 1] = -1;//表示借位
                }
                difference[i] = tmpdifference;
            }
            StringBuilder returnvalue = new StringBuilder(string.Concat(difference).TrimStart('0'));
            {
                if (returnvalue.ToString() == "")
                {
                    return "0";
                }
            }
            if (flag == -1)
            {
                returnvalue = returnvalue.Insert(0, "-");
            }
            return returnvalue.ToString();
        }
        //比较大小
        static int checkBigger(string x, string y)
        {
            if (x.Length > y.Length)
            {
                return 1;
            }
            else if (x.Length < y.Length)
            {
                return -1;
            }
            else
            {
                for (int i = 0; i < x.Length; i++)
                {
                    if (int.Parse(x[i].ToString()) > int.Parse(y[i].ToString()))
                    {
                        return 1;
                    }
                    else if (int.Parse(x[i].ToString()) < int.Parse(y[i].ToString()))
                    {
                        return -1;
                    }
                    continue;
                }
                return 0;
            }
        }
        //模拟移位
        static string Power10(string num, int n)
        {
            return num.PadRight(num.Length + n, '0');
        }

    }
}

到此这篇关于C#实现分治算法求解股票问题的文章就介绍到这了,更多相关C# 分治算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++递归与分治算法原理示例详解

    目录 1. 汉诺塔问题 2. 全排列问题 4. 归并排序 5. 快速排序 6. 棋盘覆盖问题 1. 汉诺塔问题 递归算法,分为 3 步:将 n 个 a 上的盘子借助 c 移动到 b ① 将 n-1 个 a 上的盘子借助 b 移动到 c ② 将 a 上的盘子移动到 b ③ 将 c 上的 n-1 个盘子借助 a 移动到 b 所有盘子都移动到 b 上了 void hanoi(int n,char a,char b,char c)//将n个碟子从a借助c 移到b { if(n==0) return; e

  • Java基于分治算法实现的线性时间选择操作示例

    本文实例讲述了Java基于分治算法实现的线性时间选择操作.分享给大家供大家参考,具体如下: 线性时间选择问题:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,(这里给定的线性集是无序的). 随机划分线性选择 线性时间选择随机划分法可以模仿随机化快速排序算法设计.基本思想是对输入数组进行递归划分,与快速排序不同的是,它只对划分出的子数组之一进行递归处理. 程序解释:利用随机函数产生划分基准,将数组a[p:r]划分成两个子数组a[p:i]和a[i+1:r],使a[p

  • Java基于分治算法实现的棋盘覆盖问题示例

    本文实例讲述了Java基于分治算法实现的棋盘覆盖问题.分享给大家供大家参考,具体如下: 在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方格,如何覆盖.四个L型骨牌如下图: 棋盘中的特殊方格如图: 实现的基本原理是将2^k * 2^k的棋盘分成四块2^(k - 1) * 2^(k - 1)的子棋盘,特殊方格一定在其中的一个子棋盘中,如果特殊方格在某一个子棋盘中,继续递归处理这个子棋盘,直到这个子棋盘中只有一个方格为止如果特殊方格不

  • 详解Java实现分治算法

    目录 一.前言 二.分治算法介绍 三.分治算法经典问题 3.1.二分搜索 3.2.快速排序 3.3.归并排序(逆序数) 3.4.最大子序列和 3.5.最近点对 四.结语 一.前言 在学习分治算法之前,问你一个问题,相信大家小时候都有存钱罐的经历,父母亲人如果给钱都会往自己的宝藏中存钱,我们每隔一段时间都会清点清点钱.但是一堆钱让你处理起来你可能觉得很复杂,因为数据相对于大脑有点庞大了,并且很容易算错,你可能会将它先分成几个小份算,然后再叠加起来计算总和就获得这堆钱的总数了 当然如果你觉得各个部分

  • 算法详解之分治法具体实现

    分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解. 分治法解题的一般步骤: (1)分解,将要解决的问题划分成若干规模较小的同类问题: (2)求解,当子问题划分得足够小时,用较简单的方法解决: (3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解. 一言以蔽之:分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之. 在认识分治之前很有必要先了解一下递

  • Java分治法与二分搜索算法实例分析

    本文实例讲述了Java分治法与二分搜索算法.分享给大家供大家参考,具体如下: 1.分治法 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同.递归的解这些子问题,然后将各子问题的解合并得到原问题的解. 分治法所能解决的问题一般具有以下几个特征: 1) 该问题的规模缩小到一定的程度就可以容易地解决 2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质. 3) 利用该问题分解出的子问题的解可以合并为该问题的解: 4) 该问题所分解

  • Java 详细讲解分治算法如何实现归并排序

    目录 1.什么是分治算法 分治法 基本思想 2.分治算法的体现--归并排序 归并排序 基本思想 3.代码实现 1.什么是分治算法 分治法 分治法,字面意思是"分而治之",就是把一个复杂的1问题分成两个或多个相同或相似的子问题,再把子问题分成更小的子问题直到最后子问题可以简单地直接求解,原问题的解即子问题的解的合并,这个思想是很多高效算法的基础,例如排序算法(快速排序,归并排序),傅里叶变换(快速傅里叶变换)等. 基本思想 分治法的基本思想:将一个难以直接解决的大问题,分割成一些规模较小

  • Java分治归并排序算法实例详解

    本文实例讲述了Java分治归并排序算法.分享给大家供大家参考,具体如下: 1.分治法 许多有用的算法在结构上是递归的:为了解决一个给定的问题,算法一次或多次递归地调用其自身以解决紧密相关的若干子问题.这些算法典型地遵循分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解. 分治模式在每层递归时都有三个步骤: (1)分解原问题为若干子问题,这些子问题是原问题的规模较小的实例. (2)解决这些子问题,递归地求解各子问题.然而,

  • C#实现分治算法求解股票问题

    目录 分治策略是: 可使用分治法求解的一些经典问题 分治算法 - 最大子数组问题 (1)暴力求解 (2)分治法 分治法实现大数相乘 C#实现 分治策略是: 对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解.这种算法设计策略叫做分治法. 可使用分治法求解的一些经典问题 (1)二分搜索 (2)大整数乘法 (3)Strassen矩阵乘法 (4)

  • Java算法设计与分析分治算法

    目录 一.前言 二.分治算法介绍 三.分治算法经典问题 3.1.二分搜索 3.2.快速排序 3.3.归并排序(逆序数) 3.4.最大子序列和 3.5.最近点对 四.结语 一.前言 在学习分治算法之前,问你一个问题,相信大家小时候都有存钱罐的经历,父母亲人如果给钱都会往自己的宝藏中存钱,我们每隔一段时间都会清点清点钱.但是一堆钱让你处理起来你可能觉得很复杂,因为数据相对于大脑有点庞大了,并且很容易算错,你可能会将它先分成几个小份算,然后再叠加起来计算总和就获得这堆钱的总数了 当然如果你觉得各个部分

  • Java使用分治算法实现排序数索引功能示例【二分搜索】

    本文实例讲述了Java使用分治算法实现排序数索引功能.分享给大家供大家参考,具体如下: /** * Find the first q and return the index * First method is brutal force * Second may * be Divid and Conquer * * @author open201 * */ public class Ono { /** * f(n) = s.length = n; * * @param s * @param q

  • Python基于Floyd算法求解最短路径距离问题实例详解

    本文实例讲述了Python基于Floyd算法求解最短路径距离问题.分享给大家供大家参考,具体如下: Floyd算法和Dijkstra算法,相信大家都不陌生,在最短路径距离的求解中应该算得上是最为基础和经典的两个算法了,今天就用一点时间来重新实现一下,因为本科的时候学习数据结构才开始接触的这个算法,当时唯一会用的就是C语言了,现在的话,C语言几乎已经离我远去了,个人感觉入手机器学习以来python更得我心,因为太通俗易懂了,带给你的体验自然也是非常不错的. 当然网上 有很多的算法讲解教程,我不会在

  • matlab鸟群算法求解车间调度问题详解及实现源码

    目录 一.车间调度简介 1 车间调度定义 2 传统作业车间调度 3 柔性作业车间调度 二.蝴蝶优化算法(MBO)简介 1 介绍 2 香味 3 具体算法 三.部分源代码 五.matlab版本及参考文献 一.车间调度简介 1 车间调度定义 车间调度是指根据产品制造的合理需求分配加工车间顺序,从而达到合理利用产品制造资源.提高企业经济效益的目的.车间调度问题从数学上可以描述为有n个待加工的零件要在m台机器上加工.问题需要满足的条件包括每个零件的各道工序使用每台机器不多于1次,每个零件都按照一定的顺序进

随机推荐