zoukankan      html  css  js  c++  java
  • 在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 }
  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    How to check if one path is a child of another path?
    Why there is two completely different version of Reverse for List and IEnumerable?
    在Jenkins中集成Sonarqube
    如何查看sonarqube的版本 how to check the version of sonarqube
    Queue
    BFS广度优先 vs DFS深度优先 for Binary Tree
    Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索
    102. Binary Tree Level Order Traversal 广度优先遍历
    How do I check if a type is a subtype OR the type of an object?
  • 原文地址:https://www.cnblogs.com/hapjin/p/5403384.html
Copyright © 2011-2022 走看看