五大算法之分治算法

定义:

一个先自顶向下,再自底向上的过程,一共分为三步。

1. 分–将问题分解为规模更小的子问题。
2. 治–将这些规模更小的子问题逐个击破。
3.合–将已解决的子问题合并,最终得出“母”问题的解;
 

题目一:

假设某股票1号时价格为100,后面几天的价格如下,问在哪一天买入然后哪一天卖出收益最大?

100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 94, 106, 101, 79, 94, 90, 97

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {


    private void Main() {

        //股票价格,1号开始
        int[] priceArray = { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 94, 106, 101, 79, 94, 90, 97 };
        //每日盈亏             0    13  -3   -25  20  -3  -16 -23 18  20   -7   12   -5   -7  12   -5  -22  15  -4  7
        int[] dayIncreaseArray = new int[priceArray.Length];
        dayIncreaseArray[0] = 0;
        for (int i = 1; i < dayIncreaseArray.Length; i++)
        {
            dayIncreaseArray[i] = priceArray[i] - priceArray[i - 1];
        }

        Data data = DivideAndConquerMethod(dayIncreaseArray);
        Debug.Log(string.Format("在第{0}天买入,第{1}天卖出利润最大,总利润为{2}", data.StartIndex, data.EndIndex + 1, data.Profit));

    }

    /// <summary>
    /// 买卖数据
    /// </summary>
    public class Data {

        public Data(int start, int end, int profit) {
            StartIndex = start;
            EndIndex = end;
            Profit = profit;
        }

        //买入的那天
        public int StartIndex;

        //卖出的那天
        public int EndIndex;

        //赚取的利润
        public int Profit;

    }

    /// <summary>
    /// 分治算法
    /// </summary>
    /// <param name="targetArray">股票每日盈亏</param>
    private Data DivideAndConquerMethod(int[] targetArray) {

        return DecompositionProblem(0, targetArray.Length - 1, targetArray);
    }

    /// <summary>
    /// 分解问题
    /// </summary>
    private Data DecompositionProblem(int startIndex, int endIndex, int[] targetArray) {

        if (startIndex == endIndex)
        {
            Data data = new Data(startIndex, endIndex, 0);
            return data;
        }

        int midIndex = (startIndex + endIndex) / 2;
        //第一种情况,买卖日都在左边
        Data leftPart = DecompositionProblem(startIndex, midIndex, targetArray);

        //第二种情况,买卖日都在右边边
        Data rightPart = DecompositionProblem(midIndex + 1, endIndex, targetArray);

        //第三种情况,买日在左边,卖日在右边
        Data midPart = new Data(midIndex, midIndex, 0);
        int leftTemp = targetArray[midIndex];
        int leftTotal = targetArray[midIndex];
        for (int i = midIndex - 1; i >= startIndex; i--)
        {
            leftTemp += targetArray[i];
            if (leftTemp > leftTotal)
            {
                midPart.StartIndex = i;
                leftTotal = leftTemp;
            }
        }
        midPart.Profit = leftTotal;
        int rightTemp = 0;
        int rightTotal = 0;
        for (int i = midIndex + 1; i <= endIndex; i++)
        {
            rightTemp += targetArray[i];
            if (rightTemp > rightTotal)
            {
                midPart.EndIndex = i;
                rightTotal = rightTemp;
            }
        }
        midPart.Profit += rightTotal;

        //判断三种情况种哪种利润最大
        if (leftPart.Profit >= midPart.Profit && leftPart.Profit >= rightPart.Profit)
        {
            return leftPart;
        }
        else if (midPart.Profit >= rightPart.Profit)
        {
            return midPart;
        }
        else
        {
            return rightPart;
        }

    }

}

题目二:

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
(1) 每次只能移动一个盘子;
(2) 盘子只能从柱子顶端滑出移到下一根柱子;
(3) 盘子只能叠在比它大的盘子上。
请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。
你需要原地修改栈。
示例1:
 输入:A = [2, 1, 0], B = [], C = []
 输出:C = [2, 1, 0]
示例2:
 输入:A = [1, 0], B = [], C = []
 输出:C = [1, 0]

using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {


    private void Main() {


        List<int> a = new List<int>() { 7, 6, 5, 4, 3, 2, 1 };
        List<int> b = new List<int>();
        List<int> c = new List<int>();

        DivideAndConquerMethod(a, b, c);

        foreach (var item in c)
        {
            print(item);
        }

    }


    /// <summary>
    /// 分治算法
    /// </summary>
    private void DivideAndConquerMethod(List<int> a, List<int> b, List<int> c) {

        DecompositionProblem(a.Count, a, b, c);
    }

    /// <summary>
    /// 分解问题
    /// </summary>
    private void DecompositionProblem(int n, List<int> a, List<int> b, List<int> c) {

        if (n == 1)
        {
            c.Add(a[a.Count - 1]);
            a.RemoveAt(a.Count - 1);
        }
        else
        {
            DecompositionProblem(n - 1, a, c, b);
            c.Add(a[a.Count - 1]);
            a.RemoveAt(a.Count - 1);
            DecompositionProblem(n - 1, b, a, c);
        }

    }

}

 

题目三:

猜数字游戏的规则如下:

  • 每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。

 

using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    //目标值
    int target = 2;

    private void Main() {

        int result = DivideAndConquerMethod(100);
        print(result);

    }

    /// <summary>
    /// 分治算法
    /// </summary>
    /// <param name="n">个数</param>
    /// <returns></returns>
    private int DivideAndConquerMethod(int n) {

        return DecompositionProblem(1, n);
    }

    /// <summary>
    /// 分解问题
    /// </summary>
    /// <param name="left">最小可能值</param>
    /// <param name="right">最大可能值</param>
    /// <returns></returns>
    private int DecompositionProblem(int left, int right) {
  
        int mid = (right + left) / 2;

        if (mid == target)
        {
            return mid;
        }
        else if (mid < target)
        {
            return DecompositionProblem(mid + 1, right);
        }
        else
        {
            return DecompositionProblem(left, mid - 1);
        }

    }


}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值