分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。
分治法解题的一般步骤:
(1)分解,将要解决的问题划分成若干规模较小的同类问题;
(2)求解,当子问题划分得足够小时,用较简单的方法解决;
(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
1.求解一组数组元素的最大值和最小值
public class FenZ {
public static void main(String[] args) {
int array[] = { -2, 9, 1, -4, 6 };
int[] Max = new int[1]; // java对于实参传递,是采用值传递,所以要改成数组,不能直接使用变量去计算最大值和最小值。
int[] Min = new int[1];
max_min(array, 0, array.length - 1, Max, Min);
System.out.println("最大值: " + Max[0]);
System.out.println("最小值: " + Min[0]);
}
public static void max_min(int[] a, int left, int right, int[] maxnum, int[] minnum) {
if (left == right) // 当只有一个元素时候,直接得出最大值和最小值
{
maxnum[0] = a[left];
minnum[0] = a[right];
} else if (left + 1 == right)// 当数组中有两个元素时,直接判断哪个元素大,哪个元素小
{
if (a[left] > a[right]) {
maxnum[0] = a[left];
minnum[0] = a[right];
} else {
maxnum[0] = a[right];
minnum[0] = a[left];
}
} else {
int m = (left + right) / 2;
int lmax[] = { 0 };
int lmin[] = { 0 };
int rmax[] = { 0 };
int rmin[] = { 0 };
max_min(a, left, m, lmax, lmin);
max_min(a, m + 1, right, rmax, rmin);
if (lmax[0] > rmax[0]) {
maxnum[0] = lmax[0];
} else {
maxnum[0] = rmax[0];
}
if (lmin[0] < rmin[0]) {
minnum[0] = lmin[0];
} else {
minnum[0] = rmin[0];
}
}
}
}
2.寻找假币
public class FenZ {
public static void main(String[] args) {
int arr[]={2,2,2,2,2,1,2,2,2,2,2,2,2,};
int x=method(arr,0,arr.length-1);
if(x==-1){
System.out.println("没有假币");
}else{
System.out.println("第"+(x+1)+"个金币是假币!");
}
}
private static int method(int[] arr, int l, int r) {
int re,sum1=0,sum2=0,mid;
if(l==r){ //删选到最后一个币时还存在假币
if(arr[l]==2){
return -1;
}else{
return l;
}
}
//只有两个金币时
if(l+1==r){
if(arr[l]<arr[r]){
re=l;
return re;
}else if(arr[l]>arr[r]){
re=r;
return re;
}else{
return -1;
}
}
//金币数是偶数
if((r-l+1)%2==0){
for(int i=l;i<=l+(r-l)/2;i++){ //前半段 求和
sum1=sum1+arr[i];
}
for(int i=l+(r-l)/2+1;i<=r;i++){ //后半段 求和
sum2=sum2+arr[i];
}
if(sum1>sum2){
re=method(arr,l+(r-l)/2+1,r);
return re;
}else if(sum1<sum2){
re=method(arr,l,l+(r-l)/2);
return re;
}else{
return re=-1;//sum1=sum2没有假币,返回负数
}
}
//金币数是奇数时
else{
for(int i=l;i<=l+(r-l)/2-1;i++){ //前半段 求和
sum1=sum1+arr[i];
}
for(int i=l+(r-l)/2+1;i<=r;i++){ //后半段 求和
sum2=sum2+arr[i];
}
mid=l+(r-l)/2;
if(sum1>sum2){
re=method(arr,l+(r-l)/2+1,r);
return re;
}else if(sum1<sum2){
re=method(arr,l,l+(r-l)/2-1);
return re;
}else{
if(arr[mid]==arr[l]){
return -1;//没有假币
}else{
return mid;
}
}
}
}
}
第9个金币是假币!