[I0A]查找最大子串问题的求解
来源:互联网 发布:tensorflow参数微调 编辑:程序博客网 时间:2024/05/08 23:29
Question:
假如你能够预知股票未来几天的动向,请你选择合适的买入和售出 日期 以便获得最大的利益值?
如下为股票未来几天的变动情况:
Result:
最优解为第 7 天买入,第11天卖出 获得最大单元利益为 43.
Analysis:
对于这个问题的求解我们当然可以用传统的排列组合方法来求解,即从以上任意天数中选择两天来进行计算
比如 选择day 3 和 day 9 101- 85 = 16 单元利益为16
所有的排列组合为 N*(N-1) / 2 时间复杂度为O(n^2)
然而此题依然可以有更效率的方式求解出结果,最终时间复杂度为O(n lg n).
如表格第三栏 change行,我们知道 要活得最大利益 即要求 第三行中 的 求得 最大子串 即 18 + 20 -7 +12 = 43
所以该问题转化为求解 最大子串问题.
How:
如何求解最大子串问题?这里我们仅使用 分治法(Divide and Conquer)求解
分治法分为三个步骤:Divide,Conquer,Combine.
Divide 将一个大的问题划分成若干个小的同类型的问题
Conquer 对划分后的小问题进行求解
Combine 将求解后的小问题结果合并 得出最后大问题的结果
显然 如果要将这一长串数列 求出最大子串 将这长子列化分成若干个子列 然后对子列进行求解 然后将结果合并.
我们将数列分成两个子串 即A[beg] ~ A[mid] 和 A[mid+1] ~ A[end] 两个部分
假设最大子串 出现在这两个部分,我们只要求解被划分后的两个子串
所以应该分为三部分
1.beg<= i <= j <= mid
2.mid+1<= i <= j <= end
3.beg <= i <= mid < j <= end
首先我们针对于分界处来进行计算
result find_max_crossing_subarrary(int* arr,int beg,int mid,int end){ int left_sum = INT_MIN,right_sum = INT_MIN; int left_index,right_index; int sum = 0; int i; for(i = mid;i >= beg; i--){ sum = sum + arr[i]; if(sum > left_sum) { left_sum = sum; left_index = i; } } sum = 0; for(i = mid+1;i <= end;i++){ sum = sum + arr[i]; if(sum > right_sum) { right_sum = sum; right_index = i; } } result res = {left_index,right_index,left_sum + right_sum}; return res;}
首先计算分界点左部分子串最大值,同时保存子串最大值时的标号index
然后计算分界点右边子串最大值,同时保存子串最大值时的标号
然后返回左右部分合并后的子串最大值
整个流程思路为计算左子串最大值,然后再计算右边子串最大值,然后从中间向两边计算交界处子串最大值 如下图所示
附上源代码
#include <stdio.h>#include <stdlib.h>#include <limits.h>typedef struct { int beg; int end; int sum;} result;voidarr_print(int *arr,int len);int*arr_convertor(char **argv,int *len);int*max_difference_arr(int *arr,int len);resultfind_max_crossing_subarrary(int* arr,int beg,int mid,int end);resultfind_max_subarrary(int *arr,int beg,int end);/* day012345678910111213141516 p 100113110851051028663811019410610179949097 c 013-3-2520-3-16-231820-712-5-2215-47 */int main(int argc,char **argv){ int len; int *arr = arr_convertor(argv,&len); if(len < 2) { printf("arguments must more than 2.\n"); return 0; } arr_print(arr,len); int *dif_arr = max_difference_arr(arr,len); arr_print(dif_arr,len-1); result res = find_max_subarrary(dif_arr,0,len-2); printf("max subarray begins at:%d ends at:%d.\n",res.beg,res.end+1); printf("and the max sum of the subarray is %d.\n",res.sum); printf("the max array is:"); int i = 0; for(i = res.beg;i <= res.end+1;i++) { printf("%4d",arr[i]); } free(arr); free(dif_arr); return 0;}result find_max_subarrary(int *arr,int beg,int end){ if(beg == end) { result res = {beg,end,arr[beg]}; return res; } int mid = (beg + end)/2; result left_res = find_max_subarrary(arr,beg,mid); result right_res = find_max_subarrary(arr,mid+1,end); result cross_res = find_max_crossing_subarrary(arr,beg,mid,end); if(left_res.sum >= right_res.sum && left_res.sum > cross_res.sum) return left_res; else if (right_res.sum >= left_res.sum && right_res.sum >= cross_res.sum) return right_res; else return cross_res; }result find_max_crossing_subarrary(int* arr,int beg,int mid,int end){ int left_sum = INT_MIN,right_sum = INT_MIN; int left_index,right_index; int sum = 0; int i; for(i = mid;i >= beg; i--){ sum = sum + arr[i]; if(sum > left_sum) { left_sum = sum; left_index = i; } } sum = 0; for(i = mid+1;i <= end;i++){ sum = sum + arr[i]; if(sum > right_sum) { right_sum = sum; right_index = i; } } result res = {left_index,right_index,left_sum + right_sum}; return res;}int* max_difference_arr(int *arr,int len){ int* dif_arr = malloc(sizeof(int) * (len-1)); int i; for(i = 0; i <len-1;i++){ dif_arr[i] = arr[i+1] - arr[i]; } return dif_arr;}int* arr_convertor(char **argv,int *len){ int i; char **ptr = argv; int tmp[100]; while (*++ptr != NULL) { tmp[i++] = atoi(*ptr); } *len = i; int *parr = malloc(sizeof(int)*i); for (i = 0; i < *len; i++) { parr[i] = tmp[i]; } return parr;}void arr_print(int *arr,int len){ int i; for(i = 0;i < len;i++) printf("%4d",arr[i]); printf("\n");}
测试结果如下图:
- [I0A]查找最大子串问题的求解
- 最大子序列和问题的求解
- 最大子数列和的问题求解
- 最大子序列和问题的求解
- 最大子序列和问题的求解
- 求解最大子数组问题
- 求解最大子数组问题
- 最大子序列问题求解
- 动态规划求解最大子段问题的最优解
- 算法笔记1-最大子序列和问题的求解
- 求解最大子列和问题的四种算法
- 求解最大子数组问题的三种方法
- 关于求解最大子序列和问题的总结
- 【算法学习】最大子数组问题的分治法求解
- 20160919求解最大子列和的问题
- 最大子数组问题的分治求解算法
- java最大子序列和问题的求解
- 【数据结构与算法】最大子序列和问题的求解
- On-Premise
- uvaoj-1586:分子量
- java基础20递归
- Building Maintainable Software-java篇之Write Simple Units of Code
- sdptool 设备服务查找命令使用
- [I0A]查找最大子串问题的求解
- IIC驱动学习
- git 操作技巧
- 【LA7402】colorful tree 数据结构
- 工作笔记-2014.4.3
- 中介者模式——调停者
- 排列组合 "n个球放入m个盒子m"问题 总结
- Android相机开发那些坑
- 操作系统之GDT和IDT(三)