兩種方法求解 正數數組中 兩個數相減 的最大值


一,問題描述

給定一個正數數組arr(即數組元素全是正數),找出該數組中,兩個元素相減的最大值,其中被減數的下標不小於減數的下標。

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

 

二,求解思路

下面采用兩種不同的算法來求解,第一種算法的時間復雜度為O(N),第二種算法的時間復雜度為O(N^2)。

算法一思路如下:(初始時減數為arr[0],然后算法不斷記錄比當前減數更小的減數)

maxValue初始化為0,因為當 i==j 時,arr[j] - arr[i] = 0,故 maxValue的值不可能為負數。

因此將下標 i 初始化為0,j 從下標1處開始向后掃描,並計算sub = arr[j]-arr[i]

若sub大於maxValue,則更新maxValue的值。

否則,若sub小於0,意味着找到一個新的數組元素,該數組元素比 arr[i]的值要小,則更新下標 i.

 

為什么這樣可以?

因為:當計算 sub = arr[j]-arr[i]時,arr[i]越小,則得到的sub越大。而下標 i 不斷標記更小的減數,后面的元素arr[j]與 更小的減數相減才能得到更大的差值。

比如,下圖所示數組:

 

arr[0]=18,當j=2時,max=arr[2]-arr[0]=8。當遍歷到arr[3]=12時,由於12小於18,故把下標 i 由 0 更新為 3。不需要”關注“下標為1和2的這兩個元素。因為,

若在 j>3 后面有元素使得 arr[j]-arr[1] 或者 arr[j]-arr[2]>maxValue,則該arr[j]-arr[0]一定比 arr[j]-arr[1]更大,因為arr[1]和 arr[2]都比arr[0]大。

同理:也不需要關注元素值為12 和 元素值為10之間的元素,因為,若后面某個元素減去某個 “12 到 10之間的元素(16、18、22)”比maxValue大,那么它減去12一定更大

這樣,下標 i 記錄的總是下一個比 arr[i] 更小的值(這有點類似於貪心算法的味道,每次總是貪比當前值更小的一個值,而不是如算法2中那樣依次遍歷數組中的每個元素。

 

代碼如下:

 1     //算法復雜度O(N). 找出數組arr中兩個數相減的最大值
 2     public static int maxValueOfSubtraction(int[] arr){ 
 3         int max = 0;// when j == i
 4         int i = 0;
 5         int sub;
 6         for(int j = 1; j < arr.length; j++){
 7             sub = arr[j] - arr[i];
 8             if(sub > max)
 9                 max = sub;
10             else if(sub < 0)//means there is a number smaller than a[i](i initial value is 0)
11                 i = j;
12         }
13         return max;
14     } 

 

算法二:

就是一個很普通的方法。求出 數組中所有下標大的元素減去下標小的元素,找出其中的最大值即可。代碼如下:

 1     //O(N^2) 找出數組arr中兩個數相減的最大值
 2     public static int maxValueSub(int[] arr){
 3         int max = 0;
 4         int sub;
 5         for(int i = 0; i < arr.length; i++){
 6             for(int j = i+1; j < arr.length; j++){
 7                 sub = arr[j] - arr[i];
 8                 if(sub > max)
 9                     max = sub;
10             }
11         }
12         return max;
13     }

 

一個錯誤的解法:

由於題目中要求的是 被減數的下標要大於減數的下標,故下面解法是錯誤的:

依次掃描數組中的每個元素,找出數組元素中的最大值和最小值。最大值減去最小值 即為兩個元素相減的最大值。

錯誤的原因是:最大值元素的下標 可能 比 最小值元素的下標要小。

錯誤解法代碼如下:

 1     public static int maxValueSub3(int[] arr){
 2         int min, max;
 3         int indexM = -1;int indexm = -1;
 4         min = max = arr[0];
 5         for(int i = 1; i < arr.length; i++){
 6             if(arr[i] > max)
 7             {
 8                 max = arr[i];
 9                 indexM = i;
10             }
11             else if(arr[i] < min){
12                 min = arr[i];
13                 indexm = i;
14             }
15         }
16         System.out.println("indexM" + indexM + " indexm:" + indexm);
17         return max - min;
18     }

 

三,運行時間的比較

采用 這篇文章 中提到的隨機數生成算法 來隨機生成一個數組,然后比較上面兩個算法的運行時間。

機器環境如下:

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

時間比較如下:

數組大小        算法1運行時間       算法2運行時間

100*100               1                        61

200*100               3                        158

400*100               2                        568

500*100               2                        878

100*100*10         4                        3451

 

整個代碼如下:

 1 /*
 2  * given an array, find out the max value of two numbers's distraction.
 3  * max{a[j]-a[i]} under the condition of j>=i
 4  */
 5 public class MaxValue {
 6     
 7     //算法復雜度O(N). 找出數組arr中兩個數相減的最大值
 8     public static int maxValueOfSubtraction(int[] arr){ 
 9         int max = 0;// when j == i
10         int i = 0;
11         int sub;
12         for(int j = 1; j < arr.length; j++){
13             sub = arr[j] - arr[i];
14             if(sub > max)
15                 max = sub;
16             else if(sub < 0)//means there is a number smaller than a[i](i initial value is 0)
17                 i = j;
18         }
19         return max;
20     } 
21     
22     //O(N^2) 找出數組arr中兩個數相減的最大值
23     public static int maxValueSub(int[] arr){
24         int max = 0;
25         int sub;
26         for(int i = 0; i < arr.length; i++){
27             for(int j = i+1; j < arr.length; j++){
28                 sub = arr[j] - arr[i];
29                 if(sub > max)
30                     max = sub;
31             }
32         }
33         return max;
34     }
35     
36     
37     public static void main(String[] args) {
38         int[] arr = C2_2_8.algorithm3(100*100*10);
39 
40         long start = System.currentTimeMillis();
41         int r = maxValueOfSubtraction(arr);
42         long end = System.currentTimeMillis();
43         System.out.println("maxValue=" + r + "  O(N)'s time:" + (end -start));
44         
45         long start2 = System.currentTimeMillis();
46         int r2 = maxValueSub(arr);
47         long end2 = System.currentTimeMillis();
48         System.out.println("maxValue=" + r2 + "  O(N^2)'s time:" + (end2 - start2));
49     }
50 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM