求最大子数组

1. 分治算法

     分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。
可使用分治法求解的一些经典问题
(1)二分搜索
(2)大整数乘法
(3)Strassen矩阵乘法
(4)棋盘覆盖
(5)合并排序
(6)快速排序
(7)线性时间选择
(8)最接近点对问题
(9)循环赛日程表

(10)汉诺塔

2. 股票问题


3. 使用暴力求解求最大子数组

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

namespace _501_最大子数组
{
    class Program
    {
        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[] dataArray = new int[] { 0, 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };
            int[] dataArray = new int[priceArray.Length - 1];

            //取得价格波动
            for(int i=1;i<priceArray.Length;i++)
            {
                dataArray[i - 1] = priceArray[i] - priceArray[i - 1];
            }

            //1.
            //int max = 0;
            int ivalue = 0, jvalue = 0;
            //List<int> sumList = new List<int>();

            //for (int i = 0; i < dataArray.Length; i++)
            //{
            //    int sum = dataArray[i];
            //    for (int j = i + 1; j < dataArray.Length; j++)
            //    {
            //        sum += dataArray[j];
            //        sumList.Add(sum);

            //        for (int k = 0; k < sumList.Count; k++)
            //        {
            //            if (sumList[k] > max)
            //            {
            //                max = sumList[k];
            //                ivalue = i;
            //                jvalue = j;
            //            }
            //        }
            //    }
            //}
            //2.
            int max = dataArray[0];//默认第一个为最大;
            for (int i = 0; i < dataArray.Length; i++)
            {
                //取得以i开始所有子数组
                for (int j = i; j < dataArray.Length; j++)
                {
                    int maxTemp = 0;//临时最大值

                    for (int index = i; index < j + 1; index++)
                    {
                        maxTemp += dataArray[index];
                    }
                    if (maxTemp > max)
                    {
                        max = maxTemp;
                        ivalue = i;
                        jvalue = j;
                    }
                }

            }

            Console.WriteLine("max:" + " " + max + " " + "i:" + ivalue + " " +"j:"+jvalue);

            Console.ReadKey();
        }
    }
}

4. 分治法求最大子数组

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

namespace _502_最大子数组_分治算法
{
    class Program
    {
        struct SubArray
        {
            public int startInsex;
            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[] dataArray = new int[] { 0, 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };
            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 = GetMaxArray(0, pf.Length - 1, pf);
            Console.WriteLine(subArray.startInsex);
            Console.WriteLine(subArray.endIndex);
            Console.WriteLine("从" + subArray.startInsex + "天买入" + subArray.endIndex + "天卖出");

            Console.ReadKey();
        }

        /// <summary>
        /// 用来取得array这个数组从low到high之间的最大子数组
        /// </summary>
        /// <param name="low"></param>
        /// <param name="high"></param>
        /// <param name="array"></param>
        static SubArray GetMaxArray(int low,int high,int[] array)
        {
            if(low==high)
            {
                SubArray subArray;
                subArray.startInsex = low;
                subArray.endIndex = high;
                subArray.total = array[high];
                return subArray;
            }
            int mid = (low + high) / 2;//低区间[low,mid]  高区间[mid+1,high]

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

            SubArray subArray2 = GetMaxArray(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--)
            {
                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)
                {
                    totalTemp = total2;
                    endIndex = j;
                }
            }


            SubArray subArray3;
            subArray3.startInsex = 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;
            }

        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王大匣

你的鼓励是我创作最大动力,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值