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; } } } }