1.常用算法思想有:
- 穷举算法思想: 利用计算机的强大计算,穷尽所有可能,效率低,适合没有规律可循的场合.
- 递推算法思想: 递推算法是一种理性思维模式的代表,其根据已有的数据和关系,逐步推导得到结果.
- 递归算法思想: 递归就是在程序中不断调用自身来达到 求解问题的方法.
- 分治算法思想: 分治算法是一个化繁为简的算法思想,将大问题化解为多个小问题.
- 概率算法思想: 依照概率统计的思路来求解,其往往不能得到问题的精确解,在数值计算领域应用广泛.
2.穷举算法思想
1.基本思想: 从所有可能的结果中去寻找正确的答案.
2.执行步骤:
(1)、对于一种可能的情况,计算其结果。
(2)、判断结果是否满足要求,如果不满足执行第(1)步搜索下一个可能的情况;如果满足,则表示寻找到一个正确答案。
3.穷举算法实例:
题目:今有鸡兔同笼,上有35头,下有94足,问鸡兔各几何?
代码:
import java.util.Scanner;
/**
* 今有鸡兔同笼,上有35头,下有94足,问鸡兔各几何?
*/
public class QiongJu {
public static void main(String[] args) {
int heads,foots;
Scanner input = new Scanner(System.in);
System.out.println("请输入头的个数");
heads = input.nextInt();
System.out.println("请输入足的个数");
foots = input.nextInt();
int i,j;
for (i = 1; i<=heads ; i++) {
j=heads-i;
if((2*i+4*j)==foots){
System.out.println("鸡娃子有"+i+"只");
System.out.println("小兔子有"+j+"只");
}
}
}
}
/**
* 结果:
*
*请输入头的个数
*35
*请输入足的个数
*94
*鸡娃子有23只
*小兔子有12只
*/
3.递推算法思想
1.递推思想: 递推算法是一种理性思维模式的代表,其根据已有的数据和关系,逐步推导得到结果。重点在于规律。
简单说递推:知道第一个,推出下一个,通过下一个推出下下一个,直到达到目的。
2.执行步骤:
- (1)根据已知结果和关系,求解中间结果;
- (1)判断是否达到要求,如果没有达到,则继续根据已知结果和关系求解中间结果;如果满足要求,则表示找到一个正确答案。
3.递推算法案例:
题目:斐波那契数列(如果一对两个月大的兔子以后每个月都可以生一对小兔子,而一对新生的兔子出生两个月后才可以生小兔子。也就是说,1月份出生,3月份才可以产仔。那么假定一年内没有发生兔子死亡事件,那么一年后共有多少对兔子呢?)
思路图解:
分类:逆推和顺推
代码:
import java.util.Scanner;
public class Fibonacci3 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("递推算法求解兔子产仔问题");
System.out.println("输入要计算的月份:");
int month = input.nextInt();
int num = rabbit(month);
System.out.println("第"+month+"个月时总共有兔子"+num+"只");
}
//顺递推算法求解斐波那契数列之兔子问题
private static int rabbit(int month) {
if (month<=2) return 1;
int fP=1, fL=1, f;
for (int i=3; i<=month; i++) {
f = fP + fL; //前两月兔子之和等于后一个月兔子个数
fP = fL;
fL = f;
}
return fL;
}
}
4.递归算法思想
1.算法思想:递归就是在程序中不断调用自身来达到 求解问题的方法。重点是调用自身。注意和递推进行区分。
简单说递归:要知道第一个,需要先知道下一个,要知道下一个需要先知道下下一个,直到推出一个已知的,再反推回来,得到上一个,直到第一个
2.递归分类:
- 直接递归: 在方法中调用方法本身;
- 间接递归: 即间接的调用一个方法,eg : 方法a调用方法b,方法b调用方法a。不常用。
3.注意:编写递归方法时,必须使用if语句强制在方法未执行递归调用前返回,否则将永远无法返回。
4.递归的优缺点:
优点:代码简洁清晰、可读性好、人工智能相关问题,更适宜用递归。
缺点:递归比非非递归形式的运行速度要满很多,而且递归太深会导致堆栈溢出。
5.算法实例:
题目(a):递归实现斐波那契数列的兔子问题
代码:
import java.util.Scanner;
public class Fibonacci {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("递推算法求解兔子产仔问题");
System.out.println("输入要计算的月份:");
int date = input.nextInt();
int num = compute(date);
System.out.println("第"+date+"个月时总共有兔子"+num+"只");
}
//递归计算斐波那契兔子只数
private static int compute(int month) {
if (month <2){
return 1;
}else {
//前两项之和等于后一项
return compute(month-1)+compute(month-2);
}
}
}
题目(b):利用递归思想计算阶乘,所谓阶乘 n! = n*(n-1)*(n-2)*...*2*1
代码:
import java.util.Scanner;
public class JieCheng {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入要计算阶乘的整数:");
int num = input.nextInt();
long result = fact(num);
System.out.println(num+"的阶乘为:"+result);
}
private static long fact(int num) {
if(num==1){
return 1;
}
//通式 n!= n*(n-1)!
return num*fact(num-1);
}
}
5.分治算法思想
1.思想简介:分治算法是一个化繁为简的算法思想,一般将一个复杂的问题分为多个规模较小的问题,将小规模问题的结果综合起来得到复杂问题的最终结果。
2.执行过程:
- 对于一个规模为N的问题,如果很容易解决,则直接解决,否则执行下面的步骤;
- 将问题N分解为M个规模较小的子问题,这些子问题之间是独立的,并且与原问题形式相同;
- 递归地解这些子问题;
- 将各个子问题的解合并得到原来问题的解。
3.算法实例
题目:一个袋子里有30枚硬币,其中一枚是假的,并且假的银币和真的硬币一模一样,肉眼和难分辨,目前只知道假币比真币轻一点。请问如何进行区分?
思路:采用递归分治思想进行求解:
- 首先为每一枚硬币编号,然后将所有的硬币等分为两份,放在天秤的两端。这样就将区分30枚硬币的问题变为区分两堆银币的问题;
- 因为假银币分量较轻,所以天秤较轻的一端一定含有假币;
- 再将较轻的一侧中的硬币分为两等份,重复上述的做法;
- 直到剩下最后两枚硬币,可用天秤直接找出来。
代码:
import java.util.Scanner;
public class Fenzhi {
static final int MAXNUM = 30;
public static void main(String[] args) {
int num, i;
int position;
int[] coins = new int[MAXNUM]; // 存储硬币的集合
Scanner input = new Scanner(System.in);
System.out.println("分治法求解假硬币问题");
System.out.println("请输入硬币的总个数:");
num = input.nextInt();
System.out.println("请输入硬币的质量");
for (i = 0; i < num; i++) {
coins[i] = input.nextInt();
}
position = FalseCoin(coins, 0, num - 1);
System.out.println("在上述" + num + "个硬币中,假硬币是第" + position + "个.");
}
//参数一:硬币集合 参数二:起始硬币编号 参数二:结束硬币编号 返回值:假硬币的位置
private static int FalseCoin(int[] coins, int start, int end) {
int i, sum1, sum2;
int position = 0; //假币的位置
sum1 = sum2 = 0; //初始化
if (start + 1 == end) { //最后剩两枚硬币时
if (coins[start] > coins[end]) {
position = end + 1;
return position;
} else if (coins[start] == coins[end]) {
return 0;
} else {
position = start + 1;
return position;
}
}
if ((end - start + 1) % 2 == 0) { //偶数个
for (i = start; i <= start + (end - start) / 2; i++) {
sum1 = sum1 + coins[i]; // 前半段和
}
for (i = start + (end - start) / 2 + 1; i <= end; i++) {
sum2 = sum2 + coins[i]; // 后半段和
}
if (sum1 > sum2) {
position = FalseCoin(coins, start + (end - start) / 2 + 1, end);
return position;
} else if (sum1 < sum2) {
position = FalseCoin(coins, start, start + (end - start) / 2);
return position;
} else {
}
} else { //奇数个
for (i = start; i <= start + (end - start) / 2 - 1; i++) {
sum1 = sum1 + coins[i]; // 前半段和
}
for (i = start + (end - start) / 2 + 1; i <= end; i++) {
sum2 = sum2 + coins[i]; // 后半段和
}
if (sum1 > sum2) {
position = FalseCoin(coins, start + (end - start) / 2, end);
return position;
} else if (sum1 < sum2) {
position = FalseCoin(coins, start, start + (end - start) / 2);
return position;
} else {
}
if (sum1 == sum2) { //当奇数个时两边数字和相等,中间数字肯定就是假币.
position = start + (end - start) / 2 + 1;
return position;
}
}
return position;
}
}
6.概率算法思想
1.概率算法:依照概率统计的思路来求解,其往往不能得到问题的精确解,在数值计算领域应用广泛。
2.执行流程:
- 将问题转化为相应的几何图形S,S的面积是容易计算的,问题的结果往往对应几何中某一部分的面积;
- 然后,向集合中随机撒点;
- 统计几何图形S中和S1中的点数。根据S的面积和S1面积的关系以及各种图形中的点数来计算得到结果;
- 判断上述结果是否在需要的精度之内,如果未达到精度则继续执行步骤(2),达到精度则输出近似结果。
3.概率算法分类:
- 数值概率计算;
- 蒙特卡洛(Monte Carlo)算法:
- 拉斯维加斯(Las Vegas)算法:
- 舍伍德(Sherwood)算法:
4.算法实例:
题目:蒙特卡洛算法的典型应用------计算圆周率π
代码:
import java.util.Scanner;
/**
* 蒙特卡罗算法实现计算Π
*/
public class MonteCarlo {
public static void main(String[] args) {
//输入参数n为撒点的次数,返回值为圆周率的近似值
int n;
double PI;
System.out.println("蒙特卡罗概率算法计算Π");
Scanner input = new Scanner(System.in);
System.out.println("请输入点的数量");
n = input.nextInt();
PI = MontePI(n);
System.out.println("Π约等于" + PI);
}
//蒙特卡罗算法
private static double MontePI(int n) {
double PI;
double x, y; //点的坐标
int i, sum;
sum = 0;
for (i = 0; i < n; i++) {
x = Math.random(); //产生0-1之间的随机数
y = Math.random(); //产生0-1之间的随机数
if ((x * x + y * y) <= 1) //若在阴影面积里
sum++; //计数
}
PI = 4.0 * sum / n; //计算Π
return PI;
}
}