浅谈递归和分治

 

  今天要谈论的话题主要是递归和分治。为什么要将分治和递归放在一起说?很简单,因为这两兄弟几乎不分家。就我所见过的,任何用到分治思想的算法就没有不用递归的。(如果某位朋友知道例外的,请不吝赐教。)

  所谓递归,就是自己调用自己。第一步是设置基值条件用于方法的返回,否则方法将不停的自调用,直到程序崩溃。第二部是缩小问题域的范围并调用自己来求解,直到范围缩小到触发基值条件为止。

  所谓分治,即分而治之。它也分两步:一,把一个大的问题域分解为小的问题域。二,对每个小的问题域按步骤一办理。(单从这句话来说,我们就明显看到递归的影子了。)

  概念说清楚了,接下来还是拿递归分治最经典的一个算法——递归二叉查找——来举例。

  先贴代码

 1 public class BinarySearchApp {
 2     public static final int SIZE = 10;
 3     public static int[] arrays = new int[SIZE];
 4
 5     public static int binarySearch(int lower,int upper,int key) {
 6
 7         if(lower > upper)
 8             return -1;//-1表示找不到
 9         else {
10             int current = (lower+upper)/2;
11             if(arrays[current] == key)
12                 return current;
13             else if(arrays[current] > key)
14                 return binarySearch(lower, current-1, key);//从下半截查找
15             else
16                 return binarySearch(current+1, upper, key);//从上半截查找
17         }
18     }
19
20     public static void main(String[] args) {
21         for(int i=0;i<10;i++)
22             arrays[i]=i;
23         System.out.println(binarySearch(0,SIZE-1,3));//查找3是第几个
24         System.out.println(binarySearch(0,SIZE-1,9));//查找3是第几个
25         System.out.println(binarySearch(0,SIZE-1,15));//查找3是第几个
26     }
27 }

下面是运行结果

这个算法是从一个有序数组中查找一个特定的值并返回它的索引,它很好的体现了递归和分治的思想。首先,找出数组中间位置的值,将这个值与要查找的Key比较,如果相同,返回该位置。如果小于Key,就在数组的上半截查找,如果大于Key,就在数组的下半截查找。重复上面的流程直到找到结果或返回-1。该算法的时间复杂度仅为O(LogN)。当然,在调用该方法前,最好先判断一下Key是否位于数组最小值与最大值之间,在某些情况下可以有效提高效率。

  好了,今天的随笔差不多就要就结束了。最后给大家分享一个有意思的小算法——汉诺塔问题,为什么说它有意思呢?一般解汉诺塔问题的算法都是求出一共花多少次可以移完圆盘。老实说这个真心无聊,只要高中学过数学归纳法就能很容易算出来,一点体现不出计算机的优势。我这里给出的程序可以打印出整个移动过程的步骤。

 1 import java.io.BufferedReader;
 2 import java.io.IOException;
 3 import java.io.InputStreamReader;
 4 public class Hanoi {
 5     public static void main(String[] args) throws IOException {
 6         System.out.println("Please input the number of disk:");
 7         int nDisks = getInt();
 8         doTower(nDisks,‘A‘,‘B‘,‘C‘);
 9     }
10
11     public static String getString() throws IOException {
12         BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
13         return reader.readLine();
14     }
15     public static int getInt() throws IOException {
16         BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
17         String string = reader.readLine();
18         return Integer.parseInt(string);
19     }
20     public static void doTower(int topN,char from,char inter,char to) {
21         if(topN == 1)
22             System.out.println("Disk "+topN+" from "+from+" to "+to);
23         else {
24             doTower(topN-1, from, to, inter);//from --> inter
25             System.out.println("Disk "+topN+" from "+from+" to "+to);
26             doTower(topN-1, inter, from, to);//inter --> to
27         }
28     }
29 }

运行结果贴在下面

浅谈递归和分治

时间: 2024-10-10 07:03:42

浅谈递归和分治的相关文章

浅谈递归

定义 英文定义:Recursion is the process of repeating items in a self-similar way. 具体到计算机中去: 递归:又称为递回,在数学和计算机科学中,是指在函数的定义中使用函数自身的方法. [以上定义来源为wiki]. 英文的Recursion表达的是重复发生,再次重现的意思.而对应的中文翻译”递归”确表达了两个意思:” 递”+”归”.这两个意思,正是递归思想的精髓. 递归思想 递归的基本思想是:把规模大的问题转化为规模小的相似的子问题

浅谈对点分治的一些理解

点分治是一种树分治算法(昨天听了清华大佬Ryz的课,感觉这个人讲的还可以,虽然后面有蛮多没听懂,比如再套一些七里八里的数据结构) 在解决树上路径满足某种属性的数量统计方面有着很大的作用   点分治的基本思想如下: 考虑到树上的路径对于一个点来说只有两种情况:一是经过这个点,二是不经过这个点 对于不经过这个点的情况我们可以直接往下递归处理,主要问题就是解决经过这一个点的路径 我们知道:如果一条路径要经过这个点,那么他必然是由两条在这个点不同子树中到这个点的路径组合而成(这句话真的很重要)   对于

浅谈递归调用的个人领悟

从大一开始学c,就不是挺理解递归的,最近突然有所体会: 递归调用中递归调用的函数可以把它想象成为一个树的结点,在函数中调用自身就是一个分支,直到出口条件时就是这棵树的叶子结点.叶子的值便是出口返回的值.最后从叶子结点按照你所调用的方法向上返回值,最终结束递归调用.

浅谈递归和尾递归(tail recursive)

一.递归 简单来说,递归的思想就是:把问题分解为规模更小的.具有与原问题有着相同解法的问题.比如二分查找算法,就是不断地把问题的规模变小(变成原问题的一半),而新问题与原问题有着相同的解法. 一般来讲,能用递归来解决的问题必须满足两个条件: 可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式. 存在一种基准情形(即出口),可以使递归在基准情形下退出. 以计算n!为例,递归的算法为: public static long factorial(long n){ ????????if(n=

JS 从斐波那契数列浅谈递归

一.前言 昨晚下班后,经理出于兴趣给我们技术组讲了讲算法相关的东西,全程一脸懵逼的听,中途还给我们出了一道比较有趣的爬楼问题,问题如下: 假设一个人从地面开始爬楼梯,规定一步只能爬一坎或者两坎,人只能往上走,例如爬到第一坎,很明显从地面到第一坎只有一种可选方式,从地面爬到第二坎,他可以从地面直接跨到第二坎,也可以先从地面到第一坎,再从第一坎到第二坎,也就是2种可选方式,那么求他爬到N楼一共有几种可选方式. 这道题涉及到了斐波那契数列,要求使用递归来求值,技术贼菜的我也是一脸懵逼,所以本着学习的心

cdq分治浅谈

$cdq$分治浅谈 1.分治思想 分治实际上是一种思想,这种思想就是将一个大问题划分成为一些小问题,并且这些小问题与这个大问题在某中意义上是等价的. 2.普通分治与$cdq$分治的区别 普通分治与$cdq$分治都是基于分治思想之上的算法,但是他们是有区别的.普通分治的适用条件是,产生的小问题之间互不影响,然而$cdq$分治就相对比较宽泛,小问题之间可以有影响,但是$cdq$分治不支持强制在线. 3.$cdq$分治浅谈 分治一共分为四步: 1) 将当前处理区间分为左右两个等大的子区间: 2) 递归

浅谈python中的递归

python 浅谈 递归函数 最近在自学一些python,找了些资料.自己慢慢研究到了递归函数这一章,碰到个很经典的例子.汉诺塔的移动.一开始尝试自己写的时候发现,这东西怎么可能写的出来.但是看到别人写出来以后发现,这东西真的能写出来. 本着借鉴的目的想去分析一下别人写的东西.觉得很有意思想给大家分享一下,如果有误请大家指正首先大家可以先自己想想如何能写出来. 先说一下:所谓的递归,我认为就是不断重复调用.直到return 出当前的递归循环.在我拆分的过程中,大家不妨先自己想一下结果,然后看一下

浅谈算法和数据结构

: 一 栈和队列 http://www.cnblogs.com/yangecnu/p/Introduction-Stack-and-Queue.html 最近晚上在家里看Algorithems,4th Edition,我买的英文版,觉得这本书写的比较浅显易懂,而且“图码并茂”,趁着这次机会打算好好学习做做笔记,这样也会印象深刻,这也是写这一系列文章的原因.另外普林斯顿大学在Coursera 上也有这本书同步的公开课,还有另外一门算法分析课,这门课程的作者也是这本书的作者,两门课都挺不错的. 计算

浅谈算法和数据结构: 四 快速排序

原文:浅谈算法和数据结构: 四 快速排序 上篇文章介绍了时间复杂度为O(nlgn)的合并排序,本篇文章介绍时间复杂度同样为O(nlgn)但是排序速度比合并排序更快的快速排序(Quick Sort). 快速排序是20世纪科技领域的十大算法之一 ,他由C. A. R. Hoare于1960年提出的一种划分交换排序. 快速排序也是一种采用分治法解决问题的一个典型应用.在很多编程语言中,对数组,列表进行的非稳定排序在内部实现中都使用的是快速排序.而且快速排序在面试中经常会遇到. 本文首先介绍快速排序的思