最大字段和,有点类似与最长公共子序列,这里是求连续一段求和最大的一段,比如[-2,11,-4,-4,13,-5,-2]最大求和的连续一段为11,-4,-4,13,和为16.

最基本的双针模型遍历,两个指针,分别代表最大和序列的起始和终止,算法时间复杂度O(n^2)

# 以下算法时间复杂度O(n^2)
def maxSum(arr):num = len(arr)# 记录最好的结果,这个结果是一个不断逼近的过程best_result_start =0best_result_end=0best_result =0# i为起始的指针,j为终止的指针,基于简单计算,起始位置不可能为负的,因为假如# 为负的,后移一位就会使结果变大for i in range(num):if arr[i] <0:continueelse:cur_sum = arr[i]# j指针后移更新当前的求和for j in range(i+1,num):cur_sum +=arr[j]    # 假如当前求和大于当前的最好结果,就更新当前的最好结果if cur_sum > best_result:best_result = cur_sumbest_result_start =ibest_result_end = jreturn best_result,best_result_start,best_result_end

分治的算法:分成2段,3中情况考虑,取其最大,算法时间复杂度O(nlogn)之间

#%%
# 基于分治的做法,把数组分成两个部分,最优解出现的情况:要么在左半边,要么在右半边,
# 左边的尾部+右边头部       # 针对起始为left,求最长字段和并返回,终止的标号
def start_max(arr,left,right):cur_sum =0best_result =0best_result_end =0for i in range(left,right+1):cur_sum += arr[i]        if cur_sum > best_result:best_result = cur_sumbest_result_end = ireturn best_result,best_result_end# 针对起始为right,求最长字段和并返回,终止的标号
def end_max(arr,left,right):cur_sum =0best_result =0best_result_end =0for i in range(right,left-1,-1):cur_sum += arr[i]        if cur_sum > best_result:best_result = cur_sumbest_result_end = ireturn best_result,best_result_end          # 递归的理解,一种直接看成递归到最底层,然后在最底层的处理,一种直接看成某一层直接把递归函数看成
# 你要用的变量
# 关于return和不return的理解,当你需要返回结果的时候就需要返回,在原来数组上操作的情况就可以不返回
def maxSumSub(arr,left,right):# 递归的出口,也就是最小子问题的解if left == right:best_sum = max(0,arr[left])best_i = leftbest_j = rightelse:# 划分子问题的过程,一层层进入递归,子问题不断划分,dividemid = left + (right-left)//2# 针对子问题处理,此时三个子问题# 最优解在左边left_max,left_i,left_j = maxSumSub(arr,left,mid)# 最优解在右边right_max,right_i,right_j = maxSumSub(arr,mid+1,right)# 最优解出现在左边的尾部+右边头部,最优解和起止位置best_left,best_i = end_max(arr,left,mid)best_right,best_j =start_max(arr,mid+1,right)best_sum =  best_left+ best_right# 最优解取三者中的最大值if best_sum < left_max:best_sum = left_maxbest_i = left_ibest_j = left_j            if best_sum < right_max:best_sum = right_maxbest_i = right_ibest_j = right_j  return best_sum,best_i,best_j

动态规划实现,状态方程为:b[j] = max{b[j-1]+arr[j],arr[j]},b[j]为终点为j的最大字段和,原问题最优解就是b[j]的最大值,明显这个是O(n)的时间复杂度。还是有必要说明一下,这里的 动态规划并没有对原问题进行动态规划,而是对原问题的某个解进行动态规划,或者说原问题的动态规划方程为max{max{b[j-1]+arr[j],arr[j]}}

#%%
# 动态规划的算法,状态方程,初始值
# 如何划分子问题比较好了,看成选择问题,选与不选,从尾部开始,i选的话,最大值就是end_max前面
# n-1个元素的最大值+arr[i],不选的话就是前面n-1个元素求最小字段和
# 这个工作量好大,问题规模缩小了1,然后干了分治算法一层的工作量
# 所以这种规约子问题的方案不好?
# 最大字段结束在j,那么原问题的解就是j=0,1,2..len(arr)-1
# 这么多情况里面的最大值,
# 我们定义b[j]为结束在j字段和最大值,max{b[j]} 0<=j<=len(arr)-1
# 我们只要求出了每一个b[j],最大值就是可以从里面求出来了
# 那么b如何求解了,结束在j的最大字段和,假如前面j-1最大字段和小于0的话,那就是arr[j]
# 状态方程为:b[j] = max{b[j-1]+arr[j],arr[j]}
# 这里不需要考虑arr[j]是否大于0,因为我的子问题就是定义的是结束在j的最大字段和,至于
# 最终的解是结束在不同的j上的最大字段和的最大值。# 这个方法可以知道结束位置j,没法知道起始位置i为多少啊
def maxSumDynamicProgramming(arr):# 本来是需要一个数组来记录b的,然后找b[]里面的最大值# 但是我们得到一个b,就可以更显最优结果的,我只要记录当前最优解就行了,所以只需要当前的b# b的初值就是b[0-1]的值,也就是没有元素时最大字段和为多少,为0cur_b =0# 用于记录最优的结果best_result = 0best_j = -1# 根据状态方程自底向上完成for j in range(len(arr)):# b[j] = max{b[j-1]+arr[j],arr[j]},当b[j-1]>0为左边,否则为右边,也可以直接用maxif cur_b>0:cur_b += arr[j]else:cur_b = arr[j]# 每求出一个b,就更新一下当前最优解if cur_b >= best_result:best_result = cur_bbest_j = jreturn best_result,best_j

算法优化:最大字段和,双指针遍历(n^2),分治法(nlogn),动态规划(n)相关推荐

  1. 图形结构:遍历模型,分治法,动态规划,回溯法,BFS,DFS

    图形结构,是树形结构的扩展. 我们在回溯法里面了解到几种结构:二叉树,排列树,完全n叉树,这几种解空间类型,都可以直接使用回溯法的框架解决. 二叉树,排列树,完全n叉树,都可以看成x叉树的变形,而图形 ...

  2. 常用十大算法 非递归二分查找、分治法、动态规划、贪心算法、回溯算法(骑士周游为例)、KMP、最小生成树算法:Prim、Kruskal、最短路径算法:Dijkstra、Floyd。

    十大算法 学完数据结构该学什么?当然是来巩固算法,下面介绍了十中比较常用的算法,希望能帮到大家. 包括:非递归二分查找.分治法.动态规划.贪心算法.回溯算法(骑士周游为例).KMP.最小生成树算法:P ...

  3. 五大常用算法——分治法,动态规划,回溯法,分支界限法,贪心算法

    (1) 分治法 将一个难以直接解决的大问题,分割成一些规模较小的相同问题 快速排序 快排也是分治的一个实例,快排每一趟会选定一个数,将比这个数小的放左面,比这个数大的放右面, 然后递归分治求解两个子区 ...

  4. 分治法、动态规划、贪心算法区别

    联系 分治.动态规划.贪心算法都是把一个大的问题给分解成子问题,通过解决子问题来最终解决原问题的. 区别 分治: 子问题不重复时候更适合,重复也能用,效率低,最好动态规划. 动态规划: 重复的公共子问 ...

  5. 1177: 按要求排序(指针专题)_数据结构 8 基础排序算法详解、快速排序的实现、了解分治法...

    快速排序 快速排序与冒泡排序一样,同样是属于 交换排序 叫做快速排序也是有原因的.因为它采用了 分治法的概念 其中最重要的一个概念就是 基准元素 冒泡排序每一轮将一个最大的元素挑选出并移动到右侧. 分 ...

  6. 算法设计与分析 实验二 分治法求解最近点对问题

    分治法求解最近点对问题 一.实验目的与要求 1.实验基本要求 2.实验亮点 二.实验内容与方法 三.实验步骤与过程 (一)一些准备工作 1.实验流程 2.数据生成与去除重复点 (二)暴力穷举法 1.算 ...

  7. 动态规划和分治法,贪心算法以及递归的再一次深刻理解和体会

    每次体会算法都有新的感觉,刷题越多,对算法的理解感觉也就越深刻. 下面我们来重新体会下分治法,动态规划,贪心法,递归的理解. 1.分治法: 将问题分成单独的阶段,每个阶段互相不干扰很独立,如10米长的 ...

  8. 算法设计与分析-《分治法》

    <分治法> 一.分治与递归 二.分治法适应条件与时间复杂度 三.快速幂算法 四.Strassen矩阵乘法 五.合并排序 一.分治与递归 分治的设计思想是: 将一个大问题,分割成一些规模比较 ...

  9. 算法优化---向量数组计算替代元素级别判断

    算法优化---向量数组计算替代判断 目录 前言 元素级别迭代与series,ndarray的迭代 测试 series, ndarray之间的数学计算,替代元素遍历判断. 根据数量级大小,选择适合的算法 ...

最新文章

  1. opencv数字图像处理(图像模糊)
  2. 4.3.6 无分类编址CIDR
  3. Word自定义多级符号方法
  4. 手把手视频:万能开源Hawk抓取动态网站
  5. Docker Review - dockerfile 实战_使用dockerfile制作tomcat镜像
  6. lambda Kappa iota比较
  7. keras入门之手写字识别python代码
  8. 解析XML时DTD的处理--解析时忽略,生成XML文件时加上。-- XML进阶
  9. 人们常说的微型计算机简称为 机,(精华版)国家开放大学电大专科《计算机文化基础》网络课单项选择题题库及答案...
  10. H3C 802.1X 客户端的安装使用方法
  11. 制作.ppm格式Linux内核启动logo
  12. delphi 发送html邮件,delphi发送html带附件邮件
  13. 使用JavaScript修改浏览器URL地址栏的实现代码
  14. JVM优化系列-对象内存分配和回收的细节
  15. 导致大量kworker的原因_氨氮超标的几种原因及解决办法
  16. ps语义分割_一键抠图,毛发毕现:这个GitHub项目助你快速PS
  17. 如何安装inf类型驱动程序 inno
  18. 最简单的视音频播放示例5:OpenGL播放RGB/YUV
  19. svn 服务器端密码修改,svn服务器端设置密码
  20. 删除桌面无法删除的网页快捷方式

热门文章

  1. geth访问节点_以太坊客户端Geth控制台使用及 Web3.js 使用实战
  2. android eclipse 按钮事件,android eclipse按钮的OnClick事件 - java
  3. copy所有的java文件到硬盘_将d:\java目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为.jad...
  4. 三次握手和四次挥手图解_图解TCP三次握手和四次挥手
  5. java虚拟键盘_web虚拟键盘VirtualKeyboard
  6. java ArrayList排序
  7. 【ruoyi若依】启用HTTPS/SSL后,首页重定向出错
  8. java 中 Object XML 互转,最终选择Xstream
  9. java如何跳出循环6,Java循环结结构
  10. PyTorch教程(十二):链式法则