C#学习笔记 ---最大子数组问题

暴力破解法是最简单的实现方法,只要列出数组所有可能的组合,然后找出其中和最大的组合即可;

  暴力破解法法分三层循环实现:

    1)第一层循环用于固定子数组的起始位置;

    2)第二层循环用于确定子数组的结束位置;

    3)第三层循环用于子数组和的计算,从子数组的头开始遍历到其尾,累加起来就是该子数组的和。

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[] priceFluctionArray = new int[priceArray.Length-1];
            for (int i=1; i<priceArray.Length; i++)
            {
                priceFluctionArray[i - 1] = priceArray[i] - priceArray[i - 1];
            }
            int total = priceFluctionArray[0];//默认数组的第一个元素 是最大子数组
            int startIndex = 0;
            int endIndex = 0;
           for(int i = 0; i < priceFluctionArray.Length; i++)
            {
               //取得以i为子数组起点的 所有子数组
                for (int j=i;j<priceFluctionArray.Length;j++)
                {
                    //由ij就确定了一个子数组
                    int totalTemp = 0;//临时 最大子数组的和
                    for(int index = i; index < j + 1; index++)
                    {
                        totalTemp += priceFluctionArray[index];
                    }
                    if (totalTemp > total)
                    {
                        total = totalTemp;
                        startIndex = i;
                        endIndex = j;
                    }
                }
            }
            Console.WriteLine("startIndex: " + startIndex);
            Console.WriteLine("endIndex: " + endIndex);
            Console.WriteLine("购买日期 :" + startIndex + "出售日期: " + (endIndex+1));
            Console.ReadKey();
        }
      

分治法的精髓:

    1)分--将问题分解为规模更小的子问题;

    2)治--将这些规模更小的子问题逐个击破;

    3)合--将已解决的子问题合并,最终得出“母”问题的解;

  所以原数组的最大子数组求法:

    1)分--将原数组拆分成两部分,每个部分再拆分成新的两部分......直到数组被分得只剩下一个元素;

    2)治--每个小型的数组找最大子数组,只有一个元素的数组,解就是该元素;

    3)合--将两个小型数组合并为一个数组,其中解有三种可能:

  •        左边的返回值大【low ,mid】

     

    • 中间存在一个更大的子数组和[low,high]
    • 右边的返回值大,[mid+1,high]

     返回值应选最大的;

//最大子数组的结构体
        struct SubArray
        {
           public int startIndex;
           public int endIndex;
           public int total;
        }

  static SubArray GetMaxSubArray(int low, int high, int[] array)//获取最大子数组的
        {
            if (low == high)
            {
                SubArray sub;
                sub.startIndex = low;
                sub.endIndex = high;
                sub.total = array[low];
                return sub;
            }
            int mid = (low + high) / 2;//低区间low mid   高区间 mid+1 high

            SubArray sub1 = GetMaxSubArray(low, mid, array);

            SubArray sub2 = 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--)
            {
                totalTemp += array[i];
                if (totalTemp > total1)
                {
                    total1 = totalTemp;
                    startIndex = i;
                }
            }
            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 sub3;
            sub3.startIndex = startIndex;
            sub3.endIndex = endIndex;
            sub3.total = total1 + total2;
            if (sub1.total >= sub2.total && sub1.total >= sub3.total) {
                return sub1;
            }else if (sub2.total >= sub1.total && sub2.total >= sub3.total)
            {
                return sub2;
            }
            else
            {
                return sub3;
            }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值