数据结构与算法学习——分治思想

 例如:

已知:
f(0) = 1;
f(1) = 8;
....
f(n) = f(n-1) + f(n-2);

求:
f(80);
这时候就可以用到递归算法把问题分解
f(80) = f(79) + f(78)
f(79) = f(78) + f(77)
....
一直拆分到f(0) + f(1)
递归完成

斐波那契数列了解一下。。。。

算法练习:求最大子数组

首先用暴力求解法解决:

      //已知:股票价格数组
      int[] priceArray = {100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 
                          101, 79, 94, 90, 97};
      //价格波动数组
      int[] priceVolatilityArray = new int[priceArray.Length - 1];

      //求出价格波动数组
      for (int i = 1; i < priceArray.Length; i++)
      {
          priceVolatilityArray[i - 1] = priceArray[i] - priceArray[i - 1];
      }

      int total = priceVolatilityArray[0];//默认数组的第一个元素是最大子数组
      int startIndex = 0;
      int endIndex = 0;
      for (int i = 0; i < priceVolatilityArray.Length; i++)
      {
          //取得以i为子数组起点的所有子数组
          for (int j = i; j < priceVolatilityArray.Length; j++)
          {
              //由i,j就确定了一个子数组
              int totalTemp = 0;//临时最大子数组的和
              for (int index = i; index < j + 1; index++)
              {
                  totalTemp += priceVolatilityArray[index];
              }

              if (totalTemp > total)
              {
                  total = totalTemp;
                  startIndex = i;
                  endIndex = j;
              }
          }
      }
      Console.WriteLine("startIndex = " + startIndex);
      Console.WriteLine("endIndex = " + endIndex);
      Console.ReadKey();

      /*总结:三层for循环嵌套
      /* 第一层遍历数组每个元素,目的是求从数组每个元素往后加的情况
       * 第二层为了拿到从某个元素开始往后i相加的每一个数
       * 第三层用来记录每次累加的值
       * 最后把每次累加的值和上一次的做比较得出最大值,并返回i和j的值为最大子数组开始位置 
         和结束位置
       */

用分治递归法:

        //分治法:
        //最大子数组结构体
        public struct MaxSubArray
        {
            public int startIndex; //开始时间(用来计算买入时间)
            public int endeIndex; //结束时间(卖出)
            public int total; //最大子数组之和
        }

        /// <summary>
        /// 取得array从low到high之间的最大子数组
        /// </summary>
        static MaxSubArray GetMaxSubArray(int[] array, int low, int high)
        {
            if (low == high) //递归出口:当开始时间和结束时间时同一天,也就是数组分到只有一个元素时
            {
                MaxSubArray tempMaxSubArray;
                tempMaxSubArray.startIndex = low;
                tempMaxSubArray.endeIndex = high;
                tempMaxSubArray.total = array[low];
                return tempMaxSubArray;
            }
            //三种情况:
            int mid = (low + high) / 2; //低区间:low-mid;高区间:mid+1-high;
            //low,hugh同时位于低区间时
            MaxSubArray maxSubArray1 = GetMaxSubArray(array, low, mid);
            //low,high同时位于高区间时
            MaxSubArray maxSubArray2 = GetMaxSubArray(array, mid + 1, high);
            //low在高区间,high在低区间时
            int total1 = array[mid];
            int startIndex = mid;
            int tempTotal = 0;
            //从[low,mid]中找出最大子数组[i,mid]
            for (int i = mid; i >= low; i--)
            {
                tempTotal += array[i];
                if (tempTotal > total1)
                {
                    total1 = tempTotal;
                    startIndex = i;
                }
            }
            //从[mid+1,high]中找出最大子数组[mid+1,j]
            int total2 = array[mid + 1];
            int endIndex = mid + 1;
            tempTotal = 0;
            for (int j = mid + 1; j <= high; j++)
            {
                tempTotal += array[j];
                if (tempTotal > total2)
                {
                    total2 = tempTotal;
                    endIndex = j;
                }
            }

            MaxSubArray maxSubArray3;//第一第三种情况下的子数组
            maxSubArray3.total = total1 + total2;//最大子数组之和为:从【中间往两边】依次累加的【两个最大子数组之和】相加的结果
            maxSubArray3.startIndex = startIndex;
            maxSubArray3.endeIndex = endIndex;
            /*把三次结果做比较,得出最大子数组*/
            MaxSubArray maxSubArrayA = maxSubArray1.total > maxSubArray2.total ? maxSubArray1 : maxSubArray2;
            MaxSubArray maxSubArrayB = maxSubArrayA.total > maxSubArray3.total ? maxSubArrayA : maxSubArray3;
            return maxSubArrayB;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值