求最大连续子集

问题

前两天看到一道算法题, 想了几天, 然后到网上搜了搜, 基本和我想到的相契合. 来, 题目如下:

给出一个数组, 求出和最大的连续子集. 举个例子: 数组 [1, 2, 3, 4, 5] 那和最大的就是数组本身了.

但是, 如果中间出现负数, 那情况立刻就不一样了, 你需要考虑是否能够将负数左边的内容包含进来, 从而令子集的和最大化.

下面给出本人递进的思考思路.

方案一

暴力一点, 直接遍历所有情况. 暴力破解没什么好说的, 下面是 php 代码:

$arr = []; // 一个数组
$maxSum = 0;
for($i = 0; $i < count($arr); $i++){for ($j = $i; $j < count($arr); $j++){// 计算当前子集的和$sum = 0;for ($n = $i; $n <= $j; $n++) $sum += $arr[$n];if($sum > $maxSum) $maxSum = $sum;}
}

上面代码很好理解, 将所有子集都遍历一遍, 然后比较是否是最大的和. 简单粗暴, 就是时间复杂度有些高: O(n^3)

方案二

仔细观察上面的方案, 你会发现其实是可以减少一次循环的. 第三层循环不过是将第二层的内容进行逐次累加, 也就是第二层循环的第 n 次累加结果, 正好是第 n+1次的倒数第二条结果. 如果将这样的结果进行向后传递, 就可以将第三层循环减掉了.

$arr = []; // 一个数组
$maxSum = 0;
for($i = 0; $i < count($arr); $i++){$sun = 0;for ($j = $i; $j < count($arr); $j++){$sum += $arr[$j];if($sum > $maxSum) $maxSum = $sum;}
}

看这段代码, 和方案一实现的内容其实是一样的, 但减少了一次循环, 时间复杂度直接降低了一个档次: O(n^2)

你以为到此为止了么? 天真, 如果这么简单, 那我还写个毛啊. 再来.

方案三

时间复杂度再往下降, 好吧, 我承认, 下面这段代码是我看到网上其他大佬的方案后才恍然大悟的. 恕在下愚钝. 先看代码:

$maxSum = 0; // 至今的最大值
$maxHere = 0; // 遍历到此的最大值
for($i = 0; $i < count($arr); $i++){$maxHere = max($maxHere + $arr[$i], 0);$maxSum = max($maxSum, $maxHere);
}

以上代码时间复杂度为 O(n). 很牛逼. 因为这个方法不是咱想出来的, 咱就不分析他是如何出来的了, 简单看一看她为什么能够求出结果值.

当遍历到$i 的位置时, maxHere 保存了 i-1 的最大和. 若加上当前值为正数, 则可以继续往后加, 因为正数相加必然令数字变大. 但如果相加结果为负数, 则将其重置为0 , 因为负数相加必然令数字变小. 所以 第三行 取相加结果与0的较大值.

每次遍历之后, maxHere 变量都保存了前面至当前位置的最大和, 将其与maxSum 比较即可. 至此, 即可完成时间复杂度 O(n) .

总结

其实, 当最终结果摆到我面前的时候, 我会有一种恍然大悟的感觉. 但我之前在方案二卡了几天, 没有想到 O(n) 的算法. 是思维限制了我? 是智商拉低了我? 还是仅仅因为我没有与其打过照面??

很多问题都是这样, 当答案明明白白摆在你面前的时候, 你会觉得, 哼不过如此, 故弄玄虚. 但如果不告诉你答案, 你就是绞尽脑汁, 费尽气力, 燃烧你的卡路里, 也想不到这个答案. 这感觉就像是大名鼎鼎的 NP 问题, 当答案摆在你面前时, 你能够轻而易举的验证它, 但如果不告诉你答案, 你就是得不到它.

让我想起了我当初学数学的时候, 很多题目给我的感觉也是这样. 当看过答案之后, 我会发现, 哦不过如此, so easy. 但是, 当时考试的时候就是没有写出来. 当时是如何解决这种情况呢? 大量做题. 俗话说, 熟能生巧, 熟读唐诗三百首, 不会作诗也会吟. 说的都是重复的力量. 我虽然英语是个渣渣, 但是 public cost class 这些词, 我一看就会, 为什么? 每天都在写, 想不会都难啊.

说下来, 如何解决上面的问题呢? 简单说, 多做题. 或者说, 当你解决类似的问题多了, 再次遇到它, 不用说, 下意识就会将解决方案从记忆中检索出来, 并将方案改造成适合当前场景的样子.

重在参与嘛. 将前几天困扰自己几天的问题记录一下, 虽然现在看很 low. 当然, 但愿下次看到能够想起解决方案.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508422.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据压缩算法

概述 之前在听到数据压缩的时候, 想着肯定是某些高深莫测的算法, 能够完成数据的压缩这种事情, 最近看了看, 嗯, 至少咱还是能看懂的. 无损压缩 众所周知, 不管你是exe, word, txt, dmg等等, 在存储上都是以二进制进行存储的, 所以, 在讨论压缩时, 忽略文件格式即可, 只要将…

何为真何为假

还记得第一个提出日心说的人是谁么? 没错, 哥白尼. 但是在那个年代, 所有人都认为太阳围绕着地球转的年代. 哥白尼的发现打破了大家的常识, 甚至于有过了很多年, 日心说才逐渐被大众所接受. 即使到了现在, 生活中仍然留有地心说的影子, 比如"日出" “日落” 等等, 就…

TCP 三次握手的意义

概述 在网络的传输层协议中, 存在着两大悍将: TCP 和 UDP . 从前, 我傻傻的以为自己对他们虽谈不上精通, 但还是知道的, 但是, 我错了, 我被自己问住了, 我傻了. 啥也不是. UDP (这里为了介绍简单, 就不提数据在传输过程中的失真(纠错码)等情况了. 简单介绍一下, TCP才是今天…

随机数是如何生成的

引出 在现实中, 会有抛硬币猜正反的操作, 硬币要么是正, 要么是反, 在揭晓之前, 我们谁也不知道它现在的状态. 而这, 是因为其中存在着很大的不确定因素, 如抛硬币的力度、抛硬币的角度、接硬币的力度和角度、硬币的重量、当前风速等等. 但是在计算机中, 要想生成一个随机数,…

GO 文档笔记

前言 最开始写 GO 的时候, 发现方法的注释并不支持param, return等参数, 搞得我都不知道该如何给自己的方法写文档说明了. 而且网上搜了搜也没有搜到教程, 甚是郁闷. 今天找到了GO内置的文档工具: godoc. (我用的1.14.3版本貌似不是自带工具了, 需要安装(配置代理): go get g…

长整数的乘法运算

概述 都知道, 计算机中存储整数是存在着位数限制的, 所以如果需要计算100位的数字相乘, 因为编程本身是不支持存储这么大数字的, 所以就需要自己实现, 当然了, 各个编程语言都有大数的工具包, 何必重复造轮子, 但我还是忍不住好奇他们是如何实现的, 虽然最终没有翻到他们的底层…

如何将数字转换成口语中的文本串

概述 今天突发奇想, 写一个将数字转换成中文字符串的函数. 并不是将 1234 转成 1234 , 而是将 1234 转成 一千二百三十四. 本来以为很简单, 写下来之后发现还是有些坑的. 尝试 因为我是在写完最终版本, 回过头来整理的这篇文章, 所以中间很多尝试的步骤会有所遗漏. 以下简单…

设计模式故事会

想着用讲故事的方式对各个设计模式进行一个稍微形象一些的描述. 当然, 某些因为没有想到特别好的例子, 可能比喻的并不是那么的恰当, 望赐教. 绞尽脑汁啊, 尽力贴近设计模式其本来的意图. 主要为了加强一些自己对设计模式的理解. 进入正题: 小王是一名心怀梦想的90后青年, 他独…

有了 elseif 为什么还要 switch case

引出 你有没有想过既然有了if elseif, 为什么还要设计一个switch case的语法出来呢? 按理说, 一个语言的设计角度来说, 关键词越少越好吧, 而且多出来一种选择分支也没有看出太大用处. 以下几种switch case均可以写成if else的形式(java 代码): // 形式一 switch(a){case 1:…

计算矩阵中全1子矩阵的个数

前言 最近被我大哥安利了一道算法题, 这道题说难, 还不至于我做不出来, 说简单吧, 我还想不到最优解, 等把最优解告诉我之后, 我还正好能理解. 我甚至曾经怯怯的认为, 这题就是我哥专门给我找的, 嘿嘿, 心中说不出的小欢喜. 题来了, 此题出自力扣, 原题链接: https://leetco…

GO 的方法集

前言 之前在写 GOdemo 的时候, 写了这么一段程序(大概意思): package maintype Test struct { }func (test *Test) print() {println("test fun") }func main() {Test{}.print() }结果一编译就报错了: cannot call pointer method on Test literal 差不多意思是不…

GO 切片实力踩坑

概述 GO 语言的切片这两天用了用, 可以支持切割数组的中间部分. 但今天使用中, 出了 bug, 查了半天, 发现是切片的问题, 简单写个 demo 复现当时的情况: package mainimport "fmt"func main() {a : []int{1, 2, 3, 4, 5}b : a[2:4]b[0] 9fmt.Println(a) }你以为输…

搭建本地 HTTPS 环境

前言 之前写自己的网站时, 申请过免费的https证书. 最近想在自己本地搭一个, 结果忘了当初证书是怎么来的了. 本来想着去申请个免费的证书, 但想了想, 我只需要在自己本地能使用就行了, 我自己的环境, 那当然是我说了算了. 只要能够将证书构造出来, 安装到本地就可以识别了. 搜…

《人人都是产品经理》读后感

之前读书, 一般看的都是技术、算法、数学、哲学这些方面的, 为什么突然想看这本书呢? 身为一个开发人员, 每天打交道最多的, 除了开发和测试, 就是产品了. 还记得我刚来公司的时候, 在和产品的沟通过程中, 听到最多的话估计就是: 你要懂产品, 你懂了就不会做错. 确实有很多需求…

nginx 端口转发

概述 这两天在写 go 项目, 一个 HTTP 服务器. 之前写的是 php 项目, nginx 监听80端口, 根据域名将请求分配给不同项目. 现在换了 go, 自然也想延续这个操作, 毕竟都是跑在同一台服务器上. 那么问题来了, 我的nginx 监听80端口的同时, go 服务器是无法同样监听80端口的. 这该如…

2020-08-20

前段时间有些迷茫, 有时看着自己写的代码感觉就像一坨屎, 有时写了一段逻辑总是感觉有问题, 测了一遍又一遍, 逻辑也要理好几次. 就像是进入了一种不可描述的状态, 这感觉让我很不自在. 敲代码的时间说长不长, 说短不短, 从大二开始, 到现在也小四年了, 还没有碰到过这种情况. …

beego 优雅重启

前言 最近在写 go 的项目, http 用的 beego 框架. 因为 go 不想 php, 每次代码改动都需要重启服务, 所以代码发上线之后, 如何重启服务就成了一个问题. 如果强行重启的话, 不光在重启期间的所有访问都被拒绝了, 而且在杀掉进程的时候处理中的请求也挂了. 对于一个向用户正常提…

由 go orm 引发的探索

前言 今天遇到了一个 bug, 是 golang 的orm导致的. 使用了gorm框架. 通过实现Scan与Value可以将数据库中的 json 内容解析出来, 免除了 字符串再解码的步骤. 当时报错的代码大概是这样的: type TestContent struct {Id intContent Content // 数据库中的 json 结构 }type Con…

MySQL 数据恢复

MySQL 数据恢复 前言 前两天因为没注意的误操作, 直接把某个数据表清掉了, 心慌慌. 怪自己学艺不精, 当时整了一下午也没把数据找回来. 当晚回来闭关研究, 终于在凌晨1点多整出来了, 特此记录, 以备不时之需. 对于 MySQL 数据的备份, 主要有两种: 全量备份和增量备份. 全量…

码云 Pages 搭建

因为一直在写博客, 就向着搭个 GithubPages 来展示, 一直都听说别人用它来搭建个人博客, 但一直停留在听说的阶段. 最近想着没事搞一搞, 也看看它到底是个什么东东. 不过咱一个写中文博客的, 就想着在码云上搭一个, 顺便还能被百度收录, 嘿嘿. 说干就干, 开搞. (Pages 服务只能…