題目:java
有一個無序整型數數組,如何求出這個數組排序後的任意兩個相鄰元素的最大差值?要求時間和空間複雜度儘量低。(例如:無序數組 二、三、一、四、6,排序後是一、二、三、四、6,最大差值是 6-4=2)算法
解題思路分析:數組
用一種較快的穩定排序算法(好比歸併算法,時間複雜度N*logN)給原數組排序,而後遍歷排好序的數組,每兩個相鄰元素求差,最終獲得最大差值。 測試
該解法的時間複雜度是O(N*logN),在不改變原數組的狀況下,空間複雜度是O(N)。this
可是,這個題的本意,其實不是純粹的排序問題spa
要處理這個問題,能夠從要求上出發考慮,即什麼排序算法的時間複雜度比O(N*logN)還要低? 嗯,從這點出發,彷佛能夠找到答案,回顧排序算法,比歸併算法還要快的,是計數排序以及桶排序算法了。code
那下面,就先從計數排序開始分析:對象
1.利用計數排序的思想,先求出原數組的最大值Max與最小值Min的區間長度k(k=Max-Min+1)。 blog
2.建立一個長度爲k的新數組Array。 排序
3.遍歷原數組,把原數組每個元素插入到新數組Array對應的位置,好比元素的值爲n,則插入到Array[n-min]當中。此時Array的部分位置爲空,部分位置填充了數值。
4.遍歷新數組Array,統計出Array中最大連續出現空值的次數+1,即爲相鄰元素最大差值。
例如給定無序數組 { 二、六、三、四、五、十、9 },處理過程以下圖:
該解法的時間複雜度爲O(n+k),空間複雜度一樣是O(n+k)。
下面看看其java代碼實現過程:
1 /** 2 * @author "shihuc" 3 * @date 2017年1月11日 4 */ 5 package jishuSort; 6 7 import java.io.File; 8 import java.io.FileNotFoundException; 9 import java.util.Arrays; 10 import java.util.Scanner; 11 12 /** 13 * @author chengsh05 14 * 15 */ 16 17 class MaxMin { 18 int max; 19 int min; 20 /** 21 * @return the max 22 */ 23 public int getMax() { 24 return max; 25 } 26 /** 27 * @param max the max to set 28 */ 29 public void setMax(int max) { 30 this.max = max; 31 } 32 /** 33 * @return the min 34 */ 35 public int getMin() { 36 return min; 37 } 38 /** 39 * @param min the min to set 40 */ 41 public void setMin(int min) { 42 this.min = min; 43 } 44 } 45 46 public class Algorithm { 47 48 /** 49 * @param args 50 */ 51 public static void main(String[] args) { 52 53 File file = new File("./src/jishuSort/sample.txt"); 54 Scanner sc = null; 55 try { 56 sc = new Scanner(file); 57 int N = sc.nextInt(); 58 for(int i=0; i<N; i++){ 59 int S = sc.nextInt(); 60 int data[] = new int[S]; 61 for(int j=0; j<S; j++){ 62 data[j] = sc.nextInt(); 63 } 64 MaxMin mm = getMaxMin(data); 65 int mArr[] = getMinusArray(data, mm); 66 int minus = getTarget(mArr, mm.getMin() - 1); 67 System.out.println(i + " -- > " + minus); 68 } 69 } catch (FileNotFoundException e) { 70 // TODO Auto-generated catch block 71 e.printStackTrace(); 72 } finally { 73 if(sc != null){ 74 sc.close(); 75 } 76 } 77 } 78 79 /** 80 * 在時間複雜度爲O(n)狀況下,計算出最大值與最小值 81 * 82 * @param da 83 * @return 84 */ 85 public static MaxMin getMaxMin(int da[]){ 86 MaxMin mm = new MaxMin(); 87 int max = Integer.MIN_VALUE; 88 int min = Integer.MAX_VALUE; 89 for(int i=0; i<da.length; i++){ 90 if(da[i] > max){ 91 max = da[i]; 92 } 93 if(da[i] < min){ 94 min = da[i]; 95 } 96 } 97 98 mm.setMax(max); 99 mm.setMin(min); 100 return mm; 101 } 102 103 /** 104 * 獲取最大值與最小值之間的距離 k 105 * 106 * @param mm 107 * @return k 108 */ 109 public static int getDistance(MaxMin mm){ 110 return mm.getMax() - mm.getMin() + 1; 111 } 112 113 /** 114 * 獲取差值數組,即原數組中的每一個數與最小值的差值位置處放置原數組的元素 115 * 116 * @param da 原數組 117 * @param mm 最大最小值對象 118 * @return 差值數組 119 */ 120 public static int[] getMinusArray(int da[], MaxMin mm){ 121 int K = getDistance(mm); 122 int min = mm.getMin(); 123 124 int minusArray[] = new int[K]; 125 //將數組初始化爲全mm.getMin() - 1的值, 假設,這裏的mm.getMin()比Integer.MIN_VALUE大,本身分析 126 Arrays.fill(minusArray, mm.getMin() - 1); 127 128 for(int i=0; i<da.length; i++){ 129 int n = da[i]; 130 minusArray[n - min] = n; 131 } 132 133 return minusArray; 134 } 135 136 /** 137 * 找出連續出現空值的最大個數,注意,是兩個數之間的差距,因此,最後要補加一個1 138 * 139 * @param minusArr 140 * @param empty 141 * @return 142 */ 143 public static int getTarget(int minusArr[], int empty){ 144 int size = 0; 145 int temp = 0; 146 for(int i=0; i<minusArr.length; i++){ 147 if(minusArr[i] == empty){ 148 temp++; 149 }else{ 150 if(temp > size){ 151 size = temp; 152 } 153 temp = 0; 154 } 155 } 156 return size + 1; 157 } 158 }
附加程序中用到的測試數據sample.txt:
1 2 2 7 3 2 6 3 4 5 10 9 4 5 5 2 3 1 4 6
數據中第一行,表示有多少個測試案例,後續每兩行表示一個測試裏,上一行是測試數組元素個數,下一行表示數組元素的內容。
測試運行後的結果以下:
1 0 -- > 3 2 1 -- > 2
今天,就只說到這裏吧,僅僅將計數排序實現了下,裏面有個注意的地方,就是如何判斷差值數組的內容是空,請讀者自行分析。
後續將補充桶排序的實現方案!