一,问题描述

给定一个正数数组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. Oracle的简单的创建dblink以及进行数据迁移的方法

    1. 创建dblink 语法如下: create public database link zhaobsh connect to lcoe739999 identified by Test6530 u ...

  2. 关于封装了gevent的request grequest库的使用与讨论

    最近迷上了gevent所以研究很多gevent相关的东西. 但是我现在不想写相关gevent和greenlet的东西.因为这一块内容实在太多太大太杂,我自己也还没有完全弄明白,所以等我完全搞清楚测试也 ...

  3. html5應用緩存

    HTML5使用了應用緩存,就是web應用緩存,使得在離線狀態下可以訪問web'應用. 應用緩存的優點: 離線訪問-可以在無網的狀態下訪問應用 速度-有緩存的應用加載更快 瀏覽器負載-瀏覽器只從服務器加 ...

  4. oftype 指的是集合的类型

  5. 牛客网练习赛7-B-购物

    在遥远的东方,有一家糖果专卖店. 这家糖果店将会在每天出售一些糖果,它每天都会生产出m个糖果,第i天的第j个糖果价格为C[i][j]元. 现在的你想要在接下来的n天去糖果店进行选购,你每天可以买多个糖 ...

  6. BZOJ2277[Poi2011]Strongbox——数论

    题目描述 Byteasar is a famous safe-cracker, who renounced his criminal activity and got into testing and ...

  7. Java监听器Listener的使用详解

    监听器用于监听Web应用中某些对象的创建.销毁.增加,修改,删除等动作的发生,然后作出相应的响应处理.当监听范围的对象的状态发生变化的时候,服务器自动调用监听器对象中的方法.常用于统计网站在线人数.系 ...

  8. 自学Python5.3-类和对象的简单操作

    自学Python之路 自学Python5.3-类和对象的简单操作 1. 定义一个类 定义一个类的格式如下: class 类名: 方法列表 举例1 : class Cat: #定义一个Cat类 #属性 ...

  9. BroadcastReceiver 接收系统短信广播

    BroadcastReceiver 接收系统短信广播 /* 注册广播:    * |--静态注册  (在AndroidManifest .xml 中注册)  * <receiver androi ...

  10. 【BZOJ4830】[HNOI2017]抛硬币(组合计数,拓展卢卡斯定理)

    [BZOJ4830][HNOI2017]抛硬币(组合计数,拓展卢卡斯定理) 题面 BZOJ 洛谷 题解 暴力是啥? 枚举\(A\)的次数和\(B\)的次数,然后直接组合数算就好了:\(\display ...