一,问题描述

给定一个正数数组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]更大的元素(贪心思想)

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

代码如下:

     //O(N). find out the max sum of two numbers in a positive array
public static int maxSum(int[] arr){
int i = 0;
int max = 0;//数组中所有的元素都是正数
int addValue;
for(int j = 1; j < arr.length; j++){
addValue = arr[i] + arr[j];
if(addValue > max)
max = addValue;
if(arr[j] - arr[i] > 0)
i = j;//记录更大的arr[i]
}
return max;
}

三,运行时间的比较

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

机器环境如下:

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]更小的值即可,这简直和求解两数相减的最大值一模一样!!!

代码如下:

     public static int minSum(int[] arr){
int min = Integer.MAX_VALUE;
int i = 0;
int addValue;
for(int j = 1; j < arr.length; j++){
addValue = arr[j] + arr[i];
if(addValue < min)
min = addValue;
if(arr[j] - arr[i] < 0)
i = j;
}
return min;
}

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

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

完整代码如下:

 public class MaxSum {

     //O(N). find out the max sum of two numbers in a positive array
public static int maxSum(int[] arr){
int i = 0;
int max = 0;//数组中所有的元素都是正数
int addValue;
for(int j = 1; j < arr.length; j++){
addValue = arr[i] + arr[j];
if(addValue > max)
max = addValue;
if(arr[j] - arr[i] > 0)
i = j;//记录更大的arr[i]
}
return max;
} public static int maxSum2(int[] arr){
int max = 0;
int addValue;
for(int i = 0; i < arr.length; i++){
for(int j = i+1; j < arr.length; j++){
addValue = arr[j] + arr[i];
if(addValue > max)
max = addValue;
}
}
return max;
} public static void main(String[] args) {
int[] arr = C2_2_8.algorithm3(100*100*10); long start = System.currentTimeMillis();
int r = maxSum(arr);
long end = System.currentTimeMillis();
System.out.println("maxValue=" + r + " O(N)'s time:" + (end -start)); long start2 = System.currentTimeMillis();
int r2 = maxSum2(arr);
long end2 = System.currentTimeMillis();
System.out.println("maxValue=" + r2 + " O(N^2)'s time:" + (end2 - start2));
}
}

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

  1. 2016网易实习生编程题:数组中两个数的和等于sum

    题目 找出数组中两个数的和等于sum的这两个数 解题 这个题目做过很多次了,利用HashMap,key为 sum-A[i] value为 i 当 加入HashMap时候A[i] 已经存在map中,ge ...

  2. LeetCode 421. 数组中两个数的最大异或值(Maximum XOR of Two Numbers in an Array) 71

    421. 数组中两个数的最大异或值 421. Maximum XOR of Two Numbers in an Array 题目描述 给定一个非空数组,数组中元素为 a0, a1, a2, - , a ...

  3. Java实现 LeetCode 421 数组中两个数的最大异或值

    421. 数组中两个数的最大异或值 给定一个非空数组,数组中元素为 a0, a1, a2, - , an-1,其中 0 ≤ ai < 231 . 找到 ai 和aj 最大的异或 (XOR) 运算 ...

  4. [Swift]LeetCode421. 数组中两个数的最大异或值 | Maximum XOR of Two Numbers in an Array

    Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...

  5. 421 Maximum XOR of Two Numbers in an Array 数组中两个数的最大异或值

    给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 .找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i,  j < ...

  6. 一个数组中两个数的和为N,找出这两个数字的下标

    分析,两个数字的和为N.那么这两个数字是否是唯一的呢?输出的下标是否是第一对出现的呢? 1,我们假设这两个数字是唯一的 和是唯一的,那么其中一个数字越大,另一个数字就越小.想到大小关系,我们就想到了排 ...

  7. LeetCode 数组中两个数的最大异或值

    题目链接:https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/ 题目大意: 略. 分析: 字典树 + 贪心. ...

  8. 获取数组中多个相加等于0的一组数字 javascript

    //获取数组中两个相加等于0的一对数字,比如[ [ -10, 10 ], [ -5, 5 ] ] var arr=[-5,10,1,-10,3,4,5,9] //对数组进行排序 arr.sort(fu ...

  9. Java泛型01--任意数组中两元素交换

    package com.zl.generic; /** * 交换“任意”数组 中两个元素 */ public class GenericSwapArray { public static void m ...

随机推荐

  1. pandas缺失值处理

    1.检查缺失值 为了更容易地检测缺失值(以及跨越不同的数组dtype),Pandas提供了isnull()和notnull()函数,它们也是Series和DataFrame对象的方法 - 示例1 im ...

  2. Square Root

    Square RootWhen the square root functional configuration is selected, a simplified CORDIC algorithm ...

  3. BZOJ3110[Zjoi2013]K大数查询——权值线段树套线段树

    题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...

  4. 洛谷 P2783 有机化学之神偶尔会做作弊 解题报告

    P2783 有机化学之神偶尔会做作弊 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. &quo ...

  5. suoi21 高能显示屏 (cdq分治)

    可以把翻倍的操作看作是一个查询和修改(增加刚查询得来的值)的符合操作,然后做cdq就行了 #include<bits/stdc++.h> #define pa pair<int,in ...

  6. Android微信数据导出

    在Nexus 5(Android 4.4)+WeChat 5.4,和Nexus 5(Android 5.0)+Wechat 6.0上测试可用. 获取加密的sqlite3数据库EnMicroMsg.db ...

  7. STL总结

    容器类放入的都是元素的拷贝,而非引用.所以如果需要对元素做出改动,最好是把元素存在data[N]数组中,而仅仅在容器中存放数组下标. 函数传递容器类参数时,需要传引用,否则会超时. vector ve ...

  8. models.DateTimeField(auto_now_add=True) 与 models.DateTimeField(auto_now=True)

    DateTimeField和DateField和TimeField存储的内容分别对应着datetime(),date(),time()三个对象. 对于auto_now=False和auto_now_a ...

  9. Hadoop生态圈-Zookeeper的工作原理分析

    Hadoop生态圈-Zookeeper的工作原理分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   无论是是Kafka集群,还是producer和consumer都依赖于Zoo ...

  10. Hadoop基础-完全分布式模式部署yarn日志聚集功能

    Hadoop基础-完全分布式模式部署yarn日志聚集功能 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 其实我们不用配置也可以在服务器后台通过命令行的形式查看相应的日志,但为了更方 ...