递归算法:
例一:
采用递归算法产生 的全排列。
递归的算法的关键之一是递归结束的条件:通常都是分解到只有一个元素(只有一个元素时,全排列是最简单的);
第二:全排列还要每个数字都占有每一个位置。
第三:我们应该考虑是先占有每个位置还是分解(递归)
通过下图我们可以知道,应该先占有每个位置再分解(递归)
public class sy01 {
public static int arr[] = new int[]{1, 2, 3};
public static void main(String[] args) {
perm(arr, 0, arr.length - 1);
}
private static void swap(int i, int j) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
public static void perm(int arr[], int begin, int end) {
if (end == begin) {
// 一到递归的出口就输出数组,此数组为全排列
for (int i = 0; i <= end; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
return;
} else {
for (int j = begin; j <= end; j++) {
// for循环将每个数放到begin位置中去
swap(begin, j);
perm(arr, begin + 1, end); //假设begin位置确定,
// 那么对begin+1~end中的数继续递归
swap(begin, j); //换过去后再还原,使序列保持原来的状态,不容易混乱
}
}
}
}
例二:
设 arr=[8,4,5,6,2,1,7,3],采用基于分治策略的合并排序算法解决该问题。
首先:我们还是先考虑递归结束的条件:由上图我们可以知道,当分解到只有一个元素的时候,排序是最简单的
第二:递归完成后,我们要考虑怎么进行合并:先设置一个中间数组和中间数组的指针,在给左右自数组各设置一个指针,三个指针同时指向三个数组的第一个位置,左右指针所指向的元素,进行比较,直到左右数组其中一个没有了元素,把剩余的数组元素直接赋值到中间数组,最后把中间数组重新赋值给员数组。
第三:通过上图,我们的算法是先分解(递归)在合并。
代码:
public class sy02 {
public static void main(String[] args){
int[] arr = {8, 4, 5, 6, 2, 1, 7, 3};
sort(arr,0, arr.length-1);
System.out.print(Arrays.toString(arr));
}
public static void sort(int[] arr, int left, int right){
if(left < right){
int mid = (left + right)/2;
sort(arr, left, mid);
sort(arr, mid+1, right);
merge(arr,left,right,mid);
}
}
public static void merge(int[] arr,int left, int right, int mid){
int i = left;
int j = mid + 1;
int[] temp = new int[arr.length];
int tempIndex = 0;
while(i <= mid && j <= right){
if(arr[i] <= arr[j]){
temp[tempIndex] = arr[i];
i++;
}else{
temp[tempIndex] = arr[j];
j++;
}
tempIndex++;
}
while(i <= mid){
temp[tempIndex] = arr[i];
tempIndex++;
i++;
}
while(j <= right){
temp[tempIndex] = arr[j];
tempIndex++;
j++;
}
tempIndex = 0;
while(left <= right){
arr[left] = temp[tempIndex];
left++;
tempIndex++;
}
}
}