先挖个坑,两天之内必现代码(毕竟我在网上很难找到真正用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中含有多个具有相同重数的众数,那这个代码是解决不了这个问题的。这个坑以后再填。
接下来的时间会继续实现有关分治法的几个较为经典的题目!