桶排序原理的進階應用演算法
阿新 • • 發佈:2019-01-03
問題:給指定n個無序的數列,要求輸出這n個數排序好相鄰兩個差最大值;(時間複雜度要求O(logn))
輸入:n(表示數列的長度,即n個數),接下來一行n個無序的數
輸出:排好序後相鄰兩個數之差的最大值
思路:
找出n數列的範圍(即最大值與最小值),設定n+1個桶,存放這些數;將數列範圍分成(n+1)份,平均分給n+1個桶,然後遍歷數列將每個數存放在該數所在的範圍的桶中(優化:每個桶只存放該範圍內最大的數和最小的數);最後因為是n個數,然後存在n+1個桶中,必然會至少有一個空桶,有因為每個桶存數範圍差一樣,所以只差最大的兩個數必定在空桶數最多的兩側非空桶中;差最大的為空桶數最多的右側相鄰非空桶的最小值與最左側非空桶的最大值之差!
Code:
public class MaxSub_sort { public static void main(String[] args) { Scanner as=new Scanner(System.in); int n=as.nextInt(),i,min = 0,max=0,r,x = 0,t=0; double k; int[] a=new int[n]; for(i=0;i<n;i++) { a[i]=as.nextInt(); if(i==0) { min=a[0];max=a[0]; }else { if(min>a[i]) { min=a[i]; } if(max<a[i]) { max=a[i]; } } } // System.out.println("max:"+max+",min:"+min); int[][] b=new int[n+1][3]; k=(max-min+1)/(n+1.0); // System.out.println("k:"+k); for(i=0;i<n;i++) { r=(int) ((a[i]-min)/k); // System.out.println(r); if(b[r][2]==0) { b[r][0]=a[i]; b[r][1]=a[i]; b[r][2]=-1; }else { if(b[r][0]>a[i]) { b[r][0]=a[i]; } if(b[r][1]<a[i]) { b[r][1]=a[i]; } } } // for(i=0;i<=n;i++) { // System.out.println(i+":min="+b[i][0]+",max="+b[i][1]+";"+b[i][2]); // } int max1[]=new int[2]; for(i=0;i<=n;i++) { if(b[i][2]==0) { if(t==0) { x=1;t=1; }else { x++; if(x>max1[0]) { max1[0]=x; max1[1]=i+1; } if(x==max1[0]) { if((b[max1[1]][0]-b[max1[1]-max1[0]+1][1])<(b[i][0]-b[i-x+1][1])) { max1[0]=x; max1[1]=i+1; } } } }else { t=0; } } System.out.println(b[max1[1]][0]-b[max1[1]-max1[0]-1][1]); // System.out.println(max1[0]+","+max1[1]); // System.out.println(b[max1[1]][0]+","+b[max1[1]-max1[0]-1][1]); } }
解釋:
- 輸入時讀取最大值與最小值,求出數列範圍與並平均分給(n+1)個桶,給每個桶確定範圍,初始預設每個桶為空;
- 遍歷數列,將每個數存放在對應範圍的桶中;存放時判斷桶是否為空,為空時(改變通道狀態為不為空),並將當前數賦值給桶中的最大值最小值;不為空時將當前數與桶中最大值最小值做比較,比最大值大,則將該桶的最大值改為當前數,比最小值小則將該桶最小值改為當前數;
- 最後遍歷這(n+1)個桶,找出連續空桶最多的序號,並將連續空桶最多的右邊相鄰非空桶的最小值減去左邊相鄰非空桶的最大值就為輸出的答案