先挖個坑,兩天之內必現代碼(畢竟我在網上很難找到真正用java實現的)
來填坑了,衆數問題的分治法java實現。
首先說一下其他的思路
1.暴力法:選取其中的每個數遍歷,得到每個數的重複次數,進行比較,O(n2)
2.先進行排序,O(nlgn),再去找,O(n)
3.使用額外空間(數組或者是哈希表)時間複雜度O(n),空間O(n),但是在用數組時如果數的跨度較大,比如:{1,1,1,1,1,1000000000000000000000000},這種就太不划算了。
4.分治法:
首先使用荷蘭國旗問題的劃分方法將數組劃分爲三個部分,O(n)
然後得到等於部分的重複個數largest,並與左右兩邊比較
如果largest>=左邊個數,左邊捨棄,反之左邊繼續遞歸,
右邊同理
上代碼:
這裏要說明的是,IntHolder是java中用於參數傳遞的一個類。因爲本菜雞此次的代碼是通過王曉東算法四版書上的c代碼改編,c代碼中有引用參數傳遞的過程,在函數運行中可以不斷代表參數largest的值,但是java中沒得。所以找到了這樣一個類。先貼一下它的用法:
public class valueTran {
public static void trip(IntHolder i)
{
i.value = i.value+3;
}
public static void main(String[] args) {
IntHolder aHolder = new IntHolder();
aHolder.value= 10;
trip(aHolder);
System.out.println(aHolder.value);
}
}
輸出13
一下是分治法實現衆數問題的代碼,如有問題多多指教。
public class Mode {
public static int mode(int[] a,int l,int r,IntHolder largest) {
IntHolder l1=new IntHolder();
IntHolder r1=new IntHolder();
int med=median(a, l, r);
split(a, l, r, l1, r1, med);
if(largest.value<r1.value-l1.value+1) {
largest.value=r1.value-l1.value+1;
}
System.out.println("largest:"+largest.value);
if(l1.value-l>largest.value) {
mode(a, l, l1.value-1, largest);
}
if(r-r1.value>largest.value) {
mode(a, r1.value+1, r, largest);
}
return largest.value;
}
public static void split(int[] arr,int L,int R,IntHolder l1,IntHolder r1,int key) {
int less=L-1,more=R+1;
while(L<more) {
if(arr[L]<key) {
swap(arr, L++, ++less);
}else if(arr[L]>key) {
swap(arr, L,--more);
}else {
L++;
}
}
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+",");
}
System.out.println();
System.out.print("less+1="+(less+1)+",more-1="+(more-1));
System.out.print(",key="+key);
l1.value=less+1;
r1.value=more-1;
}
public static void swap(int[] arr,int l,int r) {
int temp=arr[l];
arr[l]=arr[r];
arr[r]=temp;
}
public static int median(int[] arr,int l,int r) {
int mid=(l+r)/2;
return arr[mid];
}
public static void main(String[] args) {
int[] arr= {1,2,2,2,2,2,3,1,3,1,1,1,3,5,2,6,7};
int key=median(arr, 0, arr.length-1);
System.out.println("key="+key);
int count=0;
IntHolder l1,r1;
l1=new IntHolder();
r1=new IntHolder();
split(arr, 0, arr.length-1,l1,r1,key);
System.out.println(",l1="+l1.value+",r1="+r1.value);
System.out.println("----------------------------------------");
IntHolder largest=new IntHolder();
largest.value=0;
System.out.println("===="+mode(arr, 0, arr.length-1, largest));
}
}
貌似還有點問題,就是如果集合s中含有多個具有相同重數的衆數,那這個代碼是解決不了這個問題的。這個坑以後再填。
接下來的時間會繼續實現有關分治法的幾個較爲經典的題目!