分治法是解決問題的一種很好的思路,下面通過三種算法來了解分治法
public class DivideMethod {
/**
* 歸併排序:歸併算法的中心是歸併兩個已經有序的數組,並且遞歸調用歸併操作。 優點和缺點:比簡單排序在速度上快很多;歸併排序會佔用雙倍的存儲空間。
* 效率:歸併排序的時間複雜度是 O(N*LogN);簡單排序的複雜度是O(N2)。 每一趟歸併的時間複雜度爲 O(n), 需要O(logn)次歸併
*/
public void mergeSort(int[] list) {
int[] temp = new int[list.length];// 臨時數組
divideMergeSort(list, temp, 0, list.length - 1);
}
// 遞歸分割數據到基本單位
private void divideMergeSort(int[] list, int[] temp, int low, int upper) {
if (low == upper) {
return;
} else {
int mid = (low + upper) / 2;
divideMergeSort(list, temp, low, mid);
divideMergeSort(list, temp, mid + 1, upper);
merge(list, temp, low, mid + 1, upper);
}
}
// 歸併操作將基本單位歸併成整個有序的數組
private void merge(int[] list, int[] temp, int left, int right, int last) {
int j = 0;
int lowIndex = left;
int mid = right - 1;
int n = last - lowIndex + 1;
while (left <= mid && right <= last) {
if (list[left] < list[right]) {
temp[j++] = list[left++];
} else {
temp[j++] = list[right++];
}
}
while (left <= mid) {
temp[j++] = list[left++];
}
while (right <= last) {
temp[j++] = list[right++];
}
for (j = 0; j < n; j++) {
list[lowIndex + j] = temp[j];
}
}
/**
* x^n的分治法策略
* x^n通過分治法可以轉換爲x^(n/2)*x^(n/2) 這種裝換就會變成兩個x^(n/2)的問題,並且兩個問題是一樣的,所以我們只需要解決一個問題就可以了,
* 所以時間複雜度就會從O(n)變爲 O(LogN)
*/
public int devideXToN(int x,int n){
if(n==0){
return 1;
}
if(n==1){
return x;
}else{
if(n%2==1){
return devideXToN(x, n / 2) * devideXToN(x, n / 2) * x;
}else{
return devideXToN(x, n / 2) * devideXToN(x, n / 2);
}
}
}
/**
* 斐波那契數列是
* f(0)=0 n=0
* f(1)=1 n=1
* f(n-1)+f(n-2) n>1
*
* 如果採用遞歸求數列,有很多數字需要重複計算多次,採用分治法可以避免重複計算,
* 使計算的時間複雜段由指數級變爲線性的O(n)
* @param n
*/
public int fibonacci(int n){
int rs = 1;
int f1=1;
int f2=1;
if(n<2){
return 1;
}
//通過保存中間結果的方法可以避免多次的重複計算
for(int i=2;i<n;i++){
rs = f1+f2;
f1=f2;
f2=rs;
}
return rs;
}
}