参考leetcode第121题,大值需要出现在小值之后。这道题可以用其他更简单的方法解决,但是下面解法中用到的动态规划思想可以去解比如说最大连续子数组这种问题。

初始化

初始化一个长度为10^4的数组

import randomdata = [random.randint(0, 100000) for _ in range(10000)]
print(data)

解法

最简单的暴力算法

很容易想到一个暴力算法,时间复杂度为O(n^2),如下:

def diff_violence(data: list) -> int:max_val = 0list_size = len(data)for i in range(list_size):for j in range(i + 1, list_size):dif = data[j] - data[i]if max_val < dif:max_val = difreturn max_val

执行时间:11.581s(在i5笔记本上运行)

优化

动态规划

首先求出每两个相邻元素之间的差值,设为dif,第i个元素与第i-1个元素的差值为dif[i]。设第i个元素与前面元素的最大差值为dp[i],则有dp[i] = max(0, dp[i-1] + dif[i]),转化为代码如下:

def diff_dp_v1(data: list) -> int:max_val = 0list_size = len(data)dif = [0 for _ in range(list_size)]for i in range(1, list_size):dif[i] = data[i] - data[i - 1]dp = [0 for _ in range(list_size)]for i in range(1, list_size):dp[i] = max(0, dp[i-1] + dif[i])max_val = max(max_val, dp[i])return max_val

同时处理同一数组,暴力方法用时6.380s,动态规划方法用时0.025s,加速255倍(在i5笔记本上运行)

动态规划改进

优化掉dif和dp数组

def diff_dp_v2(data: list) -> int:max_val = 0list_size = len(data)before = 0for i in range(1, list_size):before = max(0, before + data[i] - data[i - 1])max_val = max(max_val, before)return max_val

为了测试改进之后的效果,将数组扩大至2^6,改进前用时1.847s,改进后用时1.084s。

多线程

要用多线程技术来解决这个问题就需要把各个计算模块独立出来,笔者想到的解决方法基于如下思想:

如果将一个数组分为A、B两个部分,那么最后结果可能有两个来源:

  1. A、B分别求值的最大值
  2. B的最大值减去A的最小值

所以,重新改写代码使其可以多线程运行:

from concurrent.futures import ProcessPoolExecutor
from functools import partial
from multiprocessing import cpu_countdef diff_core(data: list):max_dif = 0list_size = len(data)before = 0min_val = 1*10**10 + 1max_val = -1for i in range(list_size):if i == 0:if data[i] > max_val:max_val = data[i]if data[i] < min_val:min_val = data[i]else:if data[i] > max_val:max_val = data[i]if data[i] < min_val:min_val = data[i]before = max(0, before + data[i] - data[i - 1])max_dif = max(max_dif, before)return max_dif, min_val, max_valdef diff_multithreading(data: list, num_workers=cpu_count()) -> int:executor = ProcessPoolExecutor(max_workers=num_workers)futures = []data_len = len(data)core_len = int(data_len / num_workers)for i in range(num_workers):futures.append(executor.submit(partial(diff_core,data[i*core_len:(i+1)*core_len])))results = [future.result() for future in futures]min_res = [result[1] for result in results]max_res = [result[2] for result in results]cut_res = max([result[0] for result in results])sep_res = list()for i in range(num_workers):sep_res.append(max_res[i])sep_res.append(min_res[i])sep_res = diff_core(sep_res)[0]return max(cut_res, sep_res)

为了测试多线程的加速效果,将数组扩大至1*10^8,在16核,64G内存的linux服务器上进行测试,结果如下:

  • 未优化的动态规划:51.983s
  • 优化后的动态规划:32.959s
  • 多线程:9.124s

最大连续子数组和

可以借鉴上述思想,代码如下:

def max_sum(data: list) -> int:max_val = 0list_size = len(data)before = 0for i in range(list_size):before = max(before, before + data[i])max_val = max(max_val, before)return max_val

后记

综上,多线程算法比暴力算法快了1000倍,可以看到不同的算法设计对运行的效率有着巨大的影响。


谢评论区大佬:

def diff(data: list) -> int:max_val = 0list_size = len(data)current_min = 1000000for i in range(list_size):dif = data[i] - current_minif max_val < dif:max_val = difif data[i] < current_min:current_min = data[i]return max_val

数组 最大差值_数组两元素的最大差:从暴力到多线程相关推荐

  1. 如何得出数组里最大_相邻两数的最大差值(超巧妙解法)

    题目: 给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度O(N),且不能用非基于比较的排序 解法: 首先,输入的数组是还没有排好序的,题目要求是不能使用非基于比较的排序而且排序算法的时 ...

  2. 多线程处理list_数组两元素的最大差:从暴力到多线程

    参考leetcode第121题,大值需要出现在小值之后.这道题可以用其他更简单的方法解决,但是下面解法中用到的动态规划思想可以去解比如说最大连续子数组这种问题. 初始化 初始化一个长度为10^4的数组 ...

  3. java默认数组值_数组元素默认的初始值都是什么

    在Java中,使用数组时,如果为数组分配了内存空间,但是没有为数组元素指定初始值,系统会自动为数组元素指定初始值.数组元素的初始值与数组的数据类型有关,对于不同数据类型的数组,其数组元素的初始值是不一 ...

  4. arr数组怎么取值_记一次思否问答的问题思考:Vue为什么不能检测数组变动

    作者 | hfhan 来源 | https://segmentfault.com/a/1190000015783546 问题描述:Vue检测数据的变动是通过Object.defineProperty实 ...

  5. 快速修改数组的某个值_我用Python,3分钟快速实现,9种经典排序算法的可视化...

    最近在某网站上看到一个视频,是关于排序算法的可视化的,看着挺有意思的,也特别喜感. ▼ 6分钟演示15种排序算法 https://v.qq.com/x/page/t0396emm8oy.html 不知 ...

  6. arr数组怎么取值_【JavaScript】Array数组常规使用小结(持续更新......)

    一.概述 JavaScript的 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象. 二.创建数组四种方式 2.1.字面-隐式创建数组 var movieList = [" ...

  7. java数组包含某个值_如何检查Java数组是否包含值?

    java数组包含某个值 如何检查Java数组是否包含值? (How to Check if Java Array Contains a Value?) There are many ways to c ...

  8. java 数组的索引值_按索引访问Java数组位置的值

    我是 Java的新手,我只是在努力使用数组.我有一段代码,我在编写教程时已经编写过,但我很难理解它,如果有人能向我解释,我会很高兴. 我尝试过各种不同的方法(向我的鸭子解释,写下来等等)并且仍然无法理 ...

  9. JAVA数组扁平化整合_数组扁平化的几种处理放法

    清明节,这几天放假闲来无事,好好研究一下基础知识,今天看看数组扁平化该怎么处理: 先来看数组扁平化是什么: var arr = [1,2,3,4,[5,6,[7,8]],true] => [1, ...

最新文章

  1. 防抖 节流_关于防抖和节流
  2. 【Windows】清除win10开始菜单中失效打程序标签
  3. 安卓系列七(广播机制)
  4. 技术“摸鱼” 大神,国外小哥 5 年白拿 45 万工资!
  5. KotlinPoet
  6. 【Matlab 图像】边缘检测算法及效果演示
  7. SAP中smartforms参数
  8. 我的世界java和pe版_《我的世界》pe版不一样的方块世界
  9. C# 系统应用之清空回收站操作
  10. mysql node null_node-mysql中防止SQL注入的方法总结
  11. a*算法的时间复杂度_数据结构(1)——算法和时间复杂度
  12. 使用Maven和WebLogic 12c开发Java EE应用程序
  13. sccm终于把用户装软件的问题解决了
  14. nginx 日志和监控
  15. ASP.NET中Form验证登录后反复跳转回登录页面的问题
  16. 记录linux deploy如何进行分区安装centos7
  17. 显卡对决nbsp;NVIDIAnbsp;GTnbsp;555Mnbsp;VS…
  18. 2019年湖南省职业院校技能大赛高职组“信息安全管理与评估”赛项任务书-A卷
  19. 第九章——有ISI和AWGN信道的最佳接收机
  20. Xiangqi UVA - 1589

热门文章

  1. 信息学奥赛一本通 1150:求正整数2和n之间的完全数
  2. 信息学奥赛一本通(1320:【例6.2】均分纸牌(Noip2002))
  3. 信息学奥赛一本通(1204:爬楼梯)
  4. 训练日志 2019.1.23
  5. My Brute(HDU-3315)
  6. Charm Bracelet(POJ-3624)
  7. 骑马修栅栏(信息学奥赛一本通-T1375)
  8. 44 SD配置-销售凭证设置-定义状态参数文件
  9. unit英语读音_7款超好玩的英语启蒙APP,假期在家教娃So Easy
  10. 苹果保修期_iPhone 保修期内哪些情况可以获得免费维修?