递归

递归相当于数球游戏:

一个队人排成一排站好,每个人手里有几个球,球数不定。

我站在队伍的最后,有一个人问题我:队伍里一共有多少球?我不知道总数,只知道自己手里有2个球。因此我去问倒数第二个herry,到他为止,前面的人一共有多少球。herry也不知道,只知道自己手里有3个球。于是他去问倒数第三个人mary,mary有1个球,她去问倒数第4个人。。。这样一直传递到队伍第一个人,他手里的球数,就能算出队伍里的总球数了。

 

我们把上例中“询问”当做一个递归方法。我们在计算的过程中反复的调用这个方法(反复的询问前面的人),但是每一次调用都缩小了要解决的问题的范围(队伍前面未被询问过的人越来越少,也越来越接近最终的答案)。

 

因此递归有三个特点:

1,调用自身。

2,当它调用自身时,是为了解决更小的问题。

例如上例中,所有人都符合:到我为止的总球数=我前面所有人的总球数+我的球数

我前面所有人的总球数 就是比 到我为止的总球数 更小的问题。

而递归将不断的循环调用更小的问题,直到问题缩小到下面说的base case.

3,递归有一个根,也就是上例中的队伍第一个人。这个人不需要再问其他人了,询问到这个人时,循环就可以终止了。如果没有这样的终止条件,递归将溢出。

这个根一般是类似:

if (n==0){

  return 0; //如果一个人都没有,那么总数就是0.

}

导致递归的方法返回而没有再一次的递归调用,我们称之为基值情况(base case)。每一个递归调用都必须有一个基值条件,以避免循环无限制的进行下去。

 

这里需要说明的是,直到最内层(base case)的调用返回前,递归了多少次,就有多少个对象同时存在(这对象的输入参数和返回地址都会被压入一个栈)。因此递归是一种效率比较低的方法。时间和空间的消耗都比较大。

 

下面我们来看一个使用递归的例子:

在有序数组中,用二分法查找数据的代码。 方法find()用循环,方法recFind()用递归。

 

public class App {

    public static void main(String[] args) {
        System.out.println(App.recFind(4,0,testArray.length-1));

    }
    
    static int[] testArray = {2,3,4,5,6,7,8,10,13,15,16,19,21,34};
    
    private static int find(int searchKey, int lowBounder, int highBounder){
        int currentKey=0;
        
        while(true){
            currentKey = (lowBounder + highBounder)/2;
            if (testArray[currentKey] == searchKey){
                return currentKey;
            }
            else if (lowBounder > highBounder){
                return testArray.length;
            }
            else{
                if (testArray[currentKey] < searchKey){
                    lowBounder = currentKey + 1;
                }else{
                    highBounder = currentKey - 1;
                }
            }
            
        }
        
    }
    
    private static int recFind(int searchKey, int lowBounder, int highBounder){
        int currentKey = (lowBounder + highBounder)/2;
        
            if (testArray[currentKey] == searchKey){
                return currentKey;
            }
            else if (lowBounder > highBounder){
                return testArray.length;
            }
            else{
                if (testArray[currentKey] < searchKey){
                    return recFind(searchKey, currentKey+1, highBounder);
                }
                else{
                    return recFind(searchKey, lowBounder, currentKey-1);
                }
            }        
    }
}

用Python实现:

def bin_search(lst, target, low, high):
    while low < high:
        mid = (low + high) // 2
        if target > lst[mid]:
            low = mid + 1
        elif target < lst[mid]:
            high = mid - 1
        else:
            return mid
    return -1

a = [1,34,354,345,4,44,8,465,33,45]
a.sort()
print(bin_search(a, 345, 0, len(a)-1))

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值