递归与回溯

递归与回溯

一、递归与回溯的区别

个人理解:
递归的定义:

  • 递归是此时的状态会用用到自己上一个状态的值;

回溯的定义

  • 回溯是进行一步一步的探索,当下一个状态走完时会回到上一个状态继续寻找其他的状态,相当于一种穷举式的搜索

二、递归

递归的相关运用:搜索,排序,遍历

递归和迭代的区别
递归:

  • 遇到基本条件时会终止
  • 每次递归都需要开辟帧栈耗费内存
  • 如果无休止的递归下去会发生栈溢出错误
  • 有些问题用递归会更简单一些

迭代:

  • 会在相关条件不成立时终止
  • 执行每一次迭代时不需要开辟额外内存
  • 由于不需要开辟新的内存可以一直迭代下去
  • 某些问题的迭代解法不如递归法那样直观

实例一:
阶乘问题:输入n数返回n的阶乘。
用递归方法就很直接,简单:

public int Factorial(int n){
	if(n == 0){
	return 1;
	}
	if(n == 1){
	return 1;
	}
	else {
	return n*Factorial(n-1);
	}
}

递归的注意事项:

  • 递归有递归情况和基本情况
  • 所有递归情况都会归结到基本情况
  • 递归的效率一般低于迭代,因为需要开辟帧栈耗费内存
  • 递归算法可以用栈来实现,但会产生更多的问题,不太值得
  • 能用递归解决的问题也同样能用迭代解决

递归的算法举例:

  • 斐波那契数列(斐波那契堆),阶乘
  • 归并排序,快速排序
  • 二分搜素
  • 树的遍历(树的先序,中序,后序遍历)
  • 图的遍历(深度游戏搜索(DFS)广度优先搜索(BFS))
  • 一些动态递归问题(Dynamic Programing)
  • 分治算法
  • 汉诺塔
  • 回溯算法

实例二:
汉诺塔问题:有三根圆柱,把一根柱上的圆盘移到另一个目标圆柱上去,圆盘的摆放规则为小圆盘不能放在大圆盘上。

分析:这是一个很经典的问题,老师上课就是讲的这个例题,几乎每本算法书上都会有这个问题。
先把三根圆柱分为源柱,目标柱和辅助柱。要把源柱上的圆盘移到目标柱上去,需要先把最底层的圆盘移到目标柱上去,就要先把n-1块圆盘按圆盘摆放规则移到辅助柱上去,才能移动最底下那层,然后把辅助柱当成原来的源柱,把源柱当成辅助柱,继续递归下去,把此时的问题化为小一个规模的汉诺塔问题。

代码为:

public void TowerOfHanoi(int n,char Source,char Destination,char Auxiliary){
	if(n == 1){
		直接把源柱上的圆盘移到目标柱上去;
	}
	//把A柱上的n-1个圆盘移到C柱上,让A柱上的最后一块移到目标住上去
	TowerOfHanoi(n-1,Source,Destination,Auxiliary);
	//把C柱上的n-1块圆盘移到A柱上,让C柱上的最后一块移到目标柱上去
	TowerOfHanoi(n-1,Auxiliary,Destination,Source);
}

示例三:

判断一个数组是否已经按从从小到大的顺序排列
分析:把数组的下个数据对比,重复返回;

代码:

public Boolean isSort(int []num,int n){//n为数组长度
	if(n == 1){
		return true;	
	}
	else{
		return (num[n-1] <= num[n-2])?false:isSort(num,n-1);	
	}
}

三、回溯

回溯算法举例:

  • 二进制串,含有n位的二进制数能组成多少种不同的二进制串
  • 生成一定数量的字符串所构成的全部字符串,字符串可以从k中选
  • 背包问题
  • 生成一般字符串
  • 哈密尔顿回路
  • 图染色问题

示例一:

含有n位的二进制数能组成多少种不同的二进制串

分析:采用回溯算法进行穷举

代码:

int arr[] = new arr[];//设数组为全局变量,且长度等于n
public void Binary(int n){
	if(n < 1){
		输出arr;
	}
	else{
		arr[i-1] = 0;
		Binary(n-1);
		arr[i-1] = 1;
		Binary(n-1);	
	}
}

实例二:

生成长度为n的字符串,从k个字符,即从0到k-1去选

分析:用回溯去穷举每个字符串可能的结果

代码:

int []arr = new arr[];
public int k-string(int n,int k){
	if( n == 1){
	print("arr")
	}else{
		for(i = 0; i < k; i++){
			arr[n-1] = i;
			k-string(n-1,k);	
		}	
	}
}

你可能感兴趣的:(算法)