C#内功修炼(算法)——分治法(一)

分治法(递归的解决问题)

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


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

(1)二分搜索

(2)大整数乘法

(3)Strassen矩阵乘法

(4)棋盘覆盖

(5)合并排序

(6)快速排序

(7)线性时间选择

(8)最接近点对问题

(9)循环赛日程表

(10)汉诺塔


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


求得价格波动 最大子数组,及和最大的子数组

1,暴力求解

  private readonly int[] _priceArray = new[] {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};

    private void Violence(int[] priceArray)
    {
        int total = priceArray[0];
        int startIndex = 0;
        int endIndex = 0;

        for (int i = 0; i < priceArray.Length; i++)
        {
            for (int j = i; j < priceArray.Length; j++)
            {
                //确定一个子数组

                int totalTemp = 0;
                for (int k = i; k < j + 1; k++)
                {
                    totalTemp += priceArray[k];
                }

                if (totalTemp > total)
                {
                    total = totalTemp;
                    startIndex = i;
                    endIndex = j;
                }
            }
        }

        Debug.Log(startIndex + "---" + endIndex);   // 7---10
    }

2,分治法

 public struct SubArray
    {
        public int StartIndex;
        public int EndIndex;
        public int Total;
    }

    private SubArray DivideAndRule(int low, int high, int[] priceArray)
    {
        if (low == high)
        {
            SubArray subArray = new SubArray();
            subArray.StartIndex = low;
            subArray.EndIndex = high;
            subArray.Total = priceArray[low];

            return subArray;
        }

        int mid = (low + high)/2; //[low,mid] [mid+1,high]

        //1在低区间
        SubArray lowSubArray = DivideAndRule(low, mid, priceArray);

        //2在高区间
        SubArray highSubArray = DivideAndRule(mid + 1, high, priceArray);

        //3跨两区间
        int total1 = priceArray[mid];
        int startIndex = mid;
        int endIndex = mid + 1;
        int totalTemp = 0;

        for (int i = mid; i >= low; i--)
        {
            totalTemp += priceArray[i];
            if (totalTemp > total1)
            {
                total1 = totalTemp;
                startIndex = i;
            }
        }

        int total2 = priceArray[mid + 1];
        totalTemp = 0;
        for (int i = mid + 1; i <= high; i++)
        {
            totalTemp += priceArray[i];
            if (totalTemp > total2)
            {
                total2 = totalTemp;
                endIndex = i;
            }
        }

        SubArray currSubArray = new SubArray()
        {
            StartIndex = startIndex,
            EndIndex = endIndex,
            Total = total1 + total2
        };

        if (lowSubArray.Total > currSubArray.Total && lowSubArray.Total > highSubArray.Total)
        {
            return lowSubArray;
        }
        if (currSubArray.Total > lowSubArray.Total && currSubArray.Total > highSubArray.Total)
        {
            return currSubArray;
        }

        return highSubArray;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值