在O(N)时间内求解 正数数组中 两个数相加的 最大值

简介:

一,问题描述

给定一个正数数组arr(即数组元素全是正数),找出该数组中,两个元素相加的最大值,其中被加数的下标大于加数的下标。由加法运算的可逆性,j >i 这个条件可以去掉。

即求出: maxValue = max{arr[j]+arr[i] and j > i} 

在数组arr中没有重复的元素情况下,若被加数的下标可以等于加数的下标,则该问题变成了寻找正数数组arr中最大值的元素了。因为 max{arr[i]} + max{arr[i]} 一定比 max{arr[i]} + arr[j] 大,其中arr[j]为数组中的任意某个元素。

而《数据结构与算法分析 Java语言描述》Mark Allen Weiss著 书中第37页 2.28 题中并没有指出数组arr中的元素不通重复。

 

二,求解思路

有两种思路,一种是对数组中的每个元素,求出该元素与它后面元素的和,然后记录下最大的。

如,对于下标为 i 的元素,for each j belongs to [i+1, arr.length)需要求出 sum=arr[i]+arr[j] 其中,i belongs to [0,arr.length) and j >=i

这算法的时间复杂度为O(N^2)

第二种思路是,先将加数初始化为下标为0的那个元素(arr[i]=arr[0]),然后,j 往后扫描,若遇到比arr[i]大的元素,则下标 i=j。也就是说,i 总是记录比当前arr[i]更大的元素(贪心思想

更详细的解释,类似于这篇文章

代码如下:

复制代码
 1     //O(N). find out the max sum of two numbers in a positive array
 2     public static int maxSum(int[] arr){
 3         int i = 0;
 4         int max = 0;//数组中所有的元素都是正数
 5         int addValue;
 6         for(int j = 1; j < arr.length; j++){
 7             addValue = arr[i] + arr[j];
 8             if(addValue > max)
 9                 max = addValue;
10             if(arr[j] - arr[i] > 0)
11                 i = j;//记录更大的arr[i]
12         }
13         return max;
14     }
复制代码

 

三,运行时间的比较

采用 这篇文章 中提到的随机数生成算法 来随机生成一个数组,然后比较上面两个算法的运行时间。

机器环境如下:

OS:win7 64bit、RAM:6GB、CPU:Pentium(R)Dual-Core E5800@3.2GHz

时间比较如下:

数组大小        maxSum运行时间(O(N))       maxSum2算法2运行时间(O(N^2))

100*100             1                                        27

200*100             1                                        68

300*100             2                                        133

500*100             3                                        359

 

此外,按照同样的思路,也可以求解两个数相加的最小值了,哈哈。。。。

求两数相加的最小值,也同样是每次贪心,贪一个较arr[i]更小的值即可,这简直和求解两数相减的最大值一模一样!!!

代码如下:

复制代码
 1     public static int minSum(int[] arr){
 2         int min = Integer.MAX_VALUE;
 3         int i = 0;
 4         int addValue;
 5         for(int j = 1; j < arr.length; j++){
 6             addValue = arr[j] + arr[i];
 7             if(addValue < min)
 8                 min = addValue;
 9             if(arr[j] - arr[i] < 0)
10                 i = j;
11         }
12         return min;
13     }
复制代码

 

再扩展一下:还可以计算三个数相加的最大值。还是同样的思路,当碰到比上一次运算中的 加数 更大的数时,则把该数替换掉原来加数中最小的那个加数。(三数相加,视为有三个加数。。。^-^)

再扩展一下,是不是感觉到这个问题和 求解最大子序列和 有点联系了?  二者都是直接跳过某些不需要“关注”的元素,并总是“贪心”出 下一个候选元素。

 

完整代码如下:

复制代码
 1 public class MaxSum {
 2     
 3     //O(N). find out the max sum of two numbers in a positive array
 4     public static int maxSum(int[] arr){
 5         int i = 0;
 6         int max = 0;//数组中所有的元素都是正数
 7         int addValue;
 8         for(int j = 1; j < arr.length; j++){
 9             addValue = arr[i] + arr[j];
10             if(addValue > max)
11                 max = addValue;
12             if(arr[j] - arr[i] > 0)
13                 i = j;//记录更大的arr[i]
14         }
15         return max;
16     }
17     
18     
19     public static int maxSum2(int[] arr){
20         int max = 0;
21         int addValue;
22         for(int i = 0; i < arr.length; i++){
23             for(int j = i+1; j < arr.length; j++){
24                 addValue = arr[j] + arr[i];
25                 if(addValue > max)
26                     max = addValue;
27             }
28         }
29         return max;
30     }
31     
32     public static void main(String[] args) {
33         int[] arr = C2_2_8.algorithm3(100*100*10);
34 
35         long start = System.currentTimeMillis();
36         int r = maxSum(arr);
37         long end = System.currentTimeMillis();
38         System.out.println("maxValue=" + r + "  O(N)'s time:" + (end -start));
39         
40         long start2 = System.currentTimeMillis();
41         int r2 = maxSum2(arr);
42         long end2 = System.currentTimeMillis();
43         System.out.println("maxValue=" + r2 + "  O(N^2)'s time:" + (end2 - start2));
44     }
45 }
复制代码
相关文章
|
人工智能 语音技术 云计算
基于客户真实使用场景的云剪辑Timeline问题解答与代码实操
本文为阿里云智能媒体服务IMS「云端智能剪辑」实践指南第6期,从客户真实实践场景出发,分享一些Timeline小技巧(AI_TTS、主轨道、素材对齐),助力客户降低开发时间与成本。
135860 86
基于客户真实使用场景的云剪辑Timeline问题解答与代码实操
|
8月前
|
存储 人工智能 安全
人工智能管理体系解读(六)
ISO/IEC 42001:2023 是一项国际标准,旨在为组织建立、实施、维护和持续改进人工智能管理体系(AIMS)提供框架。该标准强调绩效评价的重要性,包括监视、测量、分析和评审,确保人工智能系统符合道德、法律及运行参数。通过内部审核和管理评审,组织可以识别改进机会,推动持续优化,确保与战略目标一致。认证有助于提升组织声誉,展示其对负责任的人工智能管理的承诺。
204 7
|
存储 NoSQL 数据挖掘
MongoDB应用案例
MongoDB应用案例
395 1
|
存储 弹性计算 安全
阿里云无影云电脑使用场景说明
阿里云无影云电脑使用场景说明,阿里云无影云电脑可用于高数据安全管控、高性能计算等要求的金融、设计、视频、教育等领域,适用于多种办公场景,如远程办公、多分支机构、安全OA、短期使用、专业制图等
459 0
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能对比
【2月更文挑战第28天】 在Android开发领域,Kotlin作为一种现代编程语言,逐渐取代了传统的Java语言。本文通过深入分析Kotlin和Java在Android平台上的性能差异,揭示两者在编译效率、运行速度以及内存消耗等方面的比较结果。我们将探讨Kotlin协程如何优化异步编程,以及Kotlin Extensions对提升开发效率的贡献。同时,文中还将介绍一些性能优化的实践技巧,帮助开发者在Kotlin环境下构建更加高效的Android应用。
|
人工智能 搜索推荐 机器人
AI Agent涌向移动终端,手机智能体开启跨端跨应用业务连接新场景
AI Agent涌向移动终端,开启跨端跨应用业务连接新场景,手机智能体将成企业AIGC应用新标配。
492 0
Mac下安装zookeeper
Mac下安装zookeeper
329 0
|
安全 数据安全/隐私保护 开发者
Mac 安装第三方软件遇到的问题解决方案汇总
Mac 安装第三方软件遇到的问题解决方案汇总
496 0
|
存储 编解码 数据挖掘
VOD(Video on Demand)
VOD(Video on Demand)是指视频点播,是一种通过互联网或其他数字传输网络,在用户需求下,按照用户选择的节目或者内容,随时、任意、快速地进行点播的服务。通俗地说,就是用户可以随时随地通过网络观看自己选择的视频内容,而不需要等待节目的播出时间。
1107 1
|
前端开发 JavaScript Java
前端LayUI框架快速上手实现登入注册
前端LayUI框架快速上手实现登入注册
378 0