递归是什么?
简而言之,方法可以调用自己。我个人在最初学习递归的时候总是容易陷入循环地思考之中。为了更好地学习递归的思想。从二分法开始深入。
通过二分法理解递归思想
给定一个指定的数值key,在自增有序数组nums中寻找其是否存在。我们可以循环目标数组,取出每一个元素与目标值相比较。这是我能够想到的最直观的解决办法。
public static int search(int key, int[] nums) {
for(int i = 0;i < nums.length;i++) {
if(nums[i] == key) {
return i;
}
}
return -1;
}
虽然问题得以解决,但是却不是很优雅的方式。假如目标数组中不存在我们指定的值key,那么我们需要对数组中所有的元素进行循环。我们已知数组是自增有序的。那我我们可以采用二分法的方式来解决问题。使用循环的方式来试一试
public static int search(int key, int[] nums) {
int left = 0;
int right = nums.length-1;
while(left <= right) {
int mid = left+(right-left)/2;
if(key > nums[mid]) {
left = mid+1;
} else if(key < nums[mid]) {
right = mid-1;
} else {
return mid;
}
}
return -1;
}
通过首先比较数组的中间位置与目标值的大小即可一次性排除一半不符合要求的元素,我们的代码大大地提高了性能。为了实现目的,我们每一次的寻找操作都是相似的,即每一次都可以排除一半不符合要求的元素。直到找到目标元素或者根本不存在目标元素。
试一试用递归的方法实现
public static int search(int key, int[] nums) {
return search(key, nums, 0, nums.length-1);
}
public static int search(int key, int[] nums, int left, int right) {
if(left > right) {
return -1;
}
int mid = left+(right-left)/2;
if(key > nums[mid]) {
return search(key, nums, mid+1, right);
} else if(key < nums[mid]) {
return search(key, nums, 0, mid-1);
} else {
return mid;
}
}
相比于前两种方法,我们的代码显得更优雅了。
趁热打铁,再来一个练习。给定一个正整数n,计算其阶乘。
// 非递归方式实现
public static int multiply(int n) {
int sum = 1;
for(int i = 1;i <= n;i++) {
sum*=i;
}
return sum;
}
// 递归方式实现
public static int super(int n) {
if(n == 1) {
return 1;
}
return n*super(n-1);
}
总结
深入分析理解,对问题进行深度剖析,对于学习和掌握所学知识点,至关重要。谨记,共勉。