分治法所能解决的问题一般具有以下几个特征:
1) 该问题的规模缩小到一定的程度就可以容易地解决
2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3) 利用该问题分解出的子问题的解可以合并为该问题的解;
4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;
第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;、
第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。
第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。
分治法在每一层递归上都有三个步骤:
step1 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
step2 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
step3 合并:将各个子问题的解合并为原问题的解。
看了那么多生硬的文字,没啥感觉还是老一套,做题!
一、寻找假币
public class FalseCoin {
public static void main(String[] args) {
int arr[]={2,2,2,2,2,1,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{
re=method(arr,mid,mid);
return re;
}
}
}
}
二、二分查找
public class BinarySearch {
public static int search(int target, int[] data,int min, int max) {
if (min > max) {
return -1;
}
int n = (min + max) / 2;
if (target > data[n]) {
min = n + 1;
}
if (target < data[n]) {
max = n - 1;
}
if (target == data[n]) {
return n;
} else {
return search(target,data, min, max);
}
}
public static void main(String[] args) {
int[] arr = { 1, 2, 7, 9, 25, 44, 66, 99 };
System.out.println(search(50, arr,0, arr.length - 1));
System.out.println(search(66, arr,0, arr.length - 1));
}
}
三、快速排序
http://blog.youkuaiyun.com/java_zero2one/article/details/51567506
四、合并排序
http://blog.youkuaiyun.com/java_zero2one/article/details/51658467