c 动态数组_Day30:连续子数组的最大和

0651f163bcba84f75dd4f8b6785eb5b5.png

剑指Offer_编程题——连续子数组的最大和

题目描述:

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

具体要求:

时间限制: C/C++ 1秒,其他语言2秒
空间限制: C/C++32M,其他语言64M

具体思路:

背景知识介绍

在做题前,首先给大家介绍一种非常典型的算法——动态规划算法。在维基百科中,动态规划算法是这样解释的:动态规划(英语:Dynamic programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。

动态规划在查找有很多重叠子问题的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题,它们的结果都逐渐被计算并被保存,从简单的问题直到整个问题都被解决。因此,动态规划保存递归时的结果,因而不会在解决同样的问题时花费时间。动态规划只能应用于有最优子结构的问题。最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。简单地说,问题能够分解成子问题来解决。

最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。无后效性。即子问题的解一旦确定,就不再改变,不受在这之后、包含它的更大的问题的求解决策影响。子问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。

具体实现一

本题是动态规划算法的典型应用,根据上述对动态规划的解释,我们可以用函数f(i)表示以第i个数字结尾的子数组的最大和,那么我们需要求出max[f(i)],其中0 <= i <= n。我们可以用如下递归公式求f(i):

f(i) = pData[i] i = 0或者f(i-1) <= 0

f(i) = f(i-1) + pData[i] i 不等于 0并且f(i-1) > 0

我们解释一下这个递归公式所表示的含义:当以第I-1个数字结尾的子数组中所有数字的和小于0时,如果把这个负数与第i个数累加,则得到的结果比第i个数字本身还要小,所以这种情况下以第I个数字结尾的子数组就是第I个数字本身。如果以第I-1个数字结尾的子数组中所有数字的和大于0,则与第i个数字累加就得到以第i个数字结尾的子数组中所有数字的和。

不过需要我们注意的是通常我们用递归的方式分析动态规划的问题,但最终都会基于循环去编码。接下来我们用java将其实现。

public 

代码效果图如图所示:

d719d69b0a93e1623f6b889de8564d5b.png

我们加上Main()在本地IDE运行,查看一下运行结果,具体实现如下:

public 

代码测试效果图如下:

08452faa7f3268c04c37916dbb27ec33.png

具体实现二

除了我们上述用动态规划的思路做出来,其实这道题有很强的规律性,因此,我们可以通过举例分析数组的规律来把此题做出来。具体的步骤如下:

从头到尾逐个累加数组中的每个数字,初始化和为0;

定义两个变量:“累加子数组和”和“最大子数组和”,第一步把数组中的第一个数字赋值给他们,然后从第二个数字开始累加,累加值放入“累加子数组和”。

1.如果当前“累加子数组和”小于0,那抛弃前面的“累加子数组和”,从下一个数字开始重新累加,“最大子数组和”的值不更新。

2.如果当前“累加子数组和”大于0,再让当前“累加子数组和”和当前的“最大子数组和”进行比较。

如果当前“累加子数组和”大于当前“最大子数组和”,则更新“最大子数组和”的值为“累加子数组和”的值。

如果当前“累加子数组和”小于当前“最大子数组和”,“最大子数组和”的值不更新。

3.再加入数组中的下一个值,“累加子数组和”进入下一轮的累加,“最大子数组和”也进入下一轮的更新。知道数组中所有值都累加完毕。

这样进行一次累加的遍历之后,就可以得到最终的最大累加和,时间复杂度是O(n)。根据以上的思路,我们可以进行一次演示,例如{1, -2, 3, 10, -4, 7, 2, -5}。具体过程如下:

b2aab4da15370d3a291fc9487e44781e.png

我们分别用java和python实现如下,不过java是从前往后遍历,而python是从后往前遍历,结果是一致的:

public 

代码效果图如图所示:

69b8a142fadf908d2527f5b86f2da1d9.png

我们加上Main()在本地IDE运行,查看一下运行结果,具体实现如下:

public 

代码测试效果图如下:

c191060f3c77920fdc9c3576b8c6f5a8.png

根据测试代码运行结果可知和我们之前与练习寻找最大子数组的结果是一致的。接下来我们利用python将其思路按照从后往前进行遍历,实现代码如下:

class 

代码效果图如图所示:

553c9f0817a361eee4cbbbd7d6f8a632.png

总结

本道题主要是通过数组考察动态规划思想,动态规划思想在数据结构与算法中也是特别的重要的,因此在做本题之前,我们首先给大家介绍了动态规划算法的基础知识,接下来通过一个递归式将其实现,不过尽管是递归,但是在实际写代码时候,还是将递归转换为迭代,这样大大减少了时间复杂度,大大提高了运行速度。并且我们还从举例找规律的角度出发来完成该题,通过找规律,并且举例子按照给定的思路走了一遍,并且分别用java和python将其实现。通过测试代码发现和我们举例子走的结果完全符合。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!

参考文献

[1]kongmin_123

[2]CC‘s World

[3]动态规划算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像的目标属于哪个类别。 定位问题:确定目标在图像的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值