传统算法-知识总结-递推+递归+分治+动态规划+贪心算法+回溯算法+分支
目录
一:算法基础
1.1.算法基础介绍
1.1.1 算法满足4条性质:
1)输入:有0个或者多个由外部提供的的量作为算法的输入
2)输出:算法产生至少一个量作为输出
3)确定性:组成算法的每条指令是清晰的和无歧义的
4)有限性:算法中每条指令的执行次数是有限的,执行每条指令的时间也是有限的。
1.1.2 算法定义:
1.1.3 算法设计过程
1.2.欧几里德算法介绍
1.2.1 定义:
欧几里德算法也被称为辗转相除法,用于计算两个整数a, b的最大公因子。符号记为:gcd(a,b).特别gcd(0, n) = 0,因为任何整数都能整除0;
1.2.2 算法内容:
通俗的讲:假设a比b大,我们要找a, b的最大公因子。第一步,用a除以b余数为y.第二步:把第一步中的除数当作被除数,把第一步中的余数当作除数再进行相除;第三步:重复第二步的步骤,一直到余数为0,结束算法,此时剩余的最后的被除数就是我们要找的最大公因子。
1.2.3 算法证明:
对于任何可以整除a和b的整数,那么它也一定可以整除(a-b)和 b.选择该整数为gcd(a, b);同理,任何可以整除a-b和b的整数,一定可以整除a和b,因此我们选择该整数为gcd(a-b,b);由此可得:gcd(a,b)=gcd(a-b,b)。
因为总有整数n,使得 a - n*b = a mod b,所以迭代可知:gcd(a-b,b)=gcd(a-2b,b)=...=gcd(a-n*b,b)=gcd(a mod b,b)。
二.递推
2.1 递推的定义
一个问题的求解需一系列的计算,在已知条件和所求问题之间总存在着某种相互联系的关系,在计算时,如果可以找到前后过程之间的数量关系(即递推式),那么,从问题出发逐步推到已知条件,此种方法叫逆推。无论顺推还是逆推,其关键是要找到递推式。
递推算法的首要问题是得到相邻的数据项间的关系(即递推关系)。递推算法避开了求通项公式的麻烦,把一个复杂的问题的求解,分解成了连续的若干步简单运算。一般说来,可以将递推算法看成是一种特殊的迭代算法
2.2 迭代法求解递推方程
不断用递推方程的右部替换左部,每次替换,随着 n 的降低在和式中多出一项,直到出现初值停止迭代,将初值代入并对和式求和
可用数学归纳法验证解的正确性
2.3 递推样例
2.3.1 一元多项式求导
(1)题目
(2)c语言求解
(3)Java语言求解
注意四个细节
- 第一个坑:数字之间可能有多个空格 如果你是用Java切割字符串的话
- 第二个坑:当系数项是0的时候输出0 0 *如:3 4 -5 2 6 1 0 1 对应输出是12 3 -10 1 6 0 0 但是题目给出的输出是 12 3 -10 1 6 0
- 第三个坑:当系数项不是0,指数是0的时候 什么也不输出 *如:3 4 -5 2 6 1 -2 0 对应输出是12 3 -10 1 6 0 (-2 0没对应的数字输出)
- 第四个坑:当输出多项式是空串的时候要输出0 0 *如:输入只有 -2 0 的时候 输出空串 但是此时必须输出0 0
代码实现:
package temp;
import java.util.ArrayList;
import java.util.Scanner;
public class algorithmtest001 {
public static void main(String arg[]) {
System.out.println("请输入整数: ");
int n,fac;
Scanner scan = new Scanner(System.in);
String str = scan.nextLine();
String[] newstr =str.split("\\s+");
ArrayList<Integer>alist = new ArrayList<Integer>();
for(int i=0;i<newstr.length;i=i+2) {
int j = i+1;
if(Integer.valueOf(newstr[i])==0){
alist.add(0);
alist.add(0);
}
if(Integer.valueOf(newstr[i])!=0&&Integer.valueOf(newstr[j])==0) {
}
if(Integer.valueOf(newstr[i])!=0&&Integer.valueOf(newstr[j])!=0) {
alist.add(Integer.valueOf(newstr[i])* Integer.valueOf(newstr[j]));
alist.add(Integer.valueOf(newstr[j])-1);
}
}
if(alist.isEmpty()){ //如果将要输出的是空字符串,那么就输出0 0
System.out.println("0 0");
}else{
for(int i=0 ;i<alist.size() ;i++){
System.out.print(alist.get(i));
if(i!=alist.size()-1){
System.out.print(" "); //行末不能有空格 控制空格的输出
}
}
}
System.out.println();
}
}
2.3.2分鱼程序
题目:
A、B、C、D、E五个人在某天夜里合伙去捕鱼,到第二天凌晨时都疲惫不堪,于是各自找地方睡觉。日上三杆,A第一个醒来,他将鱼分为五份,把多余的一条鱼扔掉,拿走自己的一份。B第二个醒来,也将鱼分为五份,把多余的一条鱼扔掉,保持走自己的一份。C、D、E依次醒来,也按同样的方法拿走鱼。问他们合伙至少捕了多少条鱼?
这个程序非常巧妙,先给a[0]一个初值为6,然后利用6去计算其他的鱼,在进行判断比较。
package temp;
import java.util.ArrayList;
import java.util.Scanner;
public class algorithmtest001 {
public static void main(String arg[]) {
int countsum = 6;
for(int i=6; ;i++)
{
int count2 =(i-1)/5*4;
int count3 = (count2-1)/5*4;
int count4 = (count3-1)/5*4;
int count5 = (count4-1)/5*4;
if(i%5==1&&count2%5==1&&count3%5==1&&count4%5==1&&count5%5==1) {
System.out.println(i);
break;
}
}
}
}
三:递归
3.1 递归:
直接或者间接地调用自身的算法成为递归算法。用函数自身给出定义的函数称为递归函数。
3.2 实例:
3.2.1 阶乘
(1)阶乘函数可递归定义为:
(2)代码实现
import java.util.Scanner;
public class algorithmtest001 {
public static void main(String arg[]) {
System.out.println("请输入整数: ");
int n,fac;
Scanner scan = new Scanner(System.in);
n= scan.nextInt();
//int []Result_Seq=new int[n];
fac = factorial(n);
System.out.println(fac);
}
public static int factorial(int m) {
if(m==0) return 1;
else return m*factorial(m-1);
}
}
3.2.2 Fibonacci数列:
(1)定义:
无穷数列1,1,2,3,5,8,13,21,34,55,........,称为Fibonacci数列,表现形式:
(2)代码实现
import java.util.Scanner;
public class algorithmtest001 {
public static void main(String arg[]) {
System.out.println("请输入整数: ");
int n,fac;
Scanner scan = new Scanner(System.in);
n= scan.nextInt();
//int []Result_Seq=new int[n];
fac = fibonacci(n);
System.out.println(fac);
}
public static int fibonacci(int m) {
if(m<=1) return 1;
else return fibonacci(m-1)+fibonacci(m-2);
}
}
3.3 经典hanoi塔问题
3.3.1 问题定义:
汉诺塔是根据一个传说形成的一个问题。汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着 64 片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
我们将 Hanoi 问题抽象为一种数学问题。首先给出如下三个柱子 A、B、C,其中 A 柱子上有从上到下从小叠到大的 N 个云盘。现要求将A柱子上的圆盘都移动到 C 柱子上,其中,每次移动都必须满足:
每次只能移动一个圆盘
小圆盘上不能放大圆盘
那么针对这个数学问题,就可以提出相关问题:
移动 N 个圆盘最少需要多少次
第 M 步移动的是哪个圆盘以及圆盘移动方向
解题:设总共有 N 个圆盘,Steps表示总移动次数
3.3.2 解题思路
3.3.3Java代码实现hanoi塔
import java.util.ArrayList;
import java.util.Scanner;
public class algorithmtest001 {
static long s = 0;
public static void main(String args[]) {
System.out.println("开始hanoi塔游戏 ");
int n = 0;
Scanner console = new Scanner(System.in);
n = console.nextInt();
System.out.print