常用算法思想

1 穷举算法

穷举算法(Exhaustive Attack method)是最简单的一种算法.其依赖于计算机的强大
算能力,来穷尽每一种可能的情况,从而达到求解问题的目的。穷举算法效率并不高,但是适合于一些没有明显规律可循的场合。

  • 穷举算法基本思想
    穷举算法的基本思想就是从所有可能的情况中搜索正确的答案,其执行步骤如下:
  1. 对于一种可能的情况,计算其结果。
  2. 判断结果是否满足要求,如果不满足则执行第 1 步来搜索下一个可能的情况;如果满足要求,则表示寻找到一个正确的答案。

在使用穷举算法时,需要明确问题的答案的范围,这样才可以在指定范围内搜索答案。指定范围之后,就可以使用循环语句和条件判断语句逐步验证候选答案的正确性,从而得到正确答案

import java.util.Scanner;

// 穷举法求解鸡兔同笼问题
public class ChickenAndRabbit {
    static int chicken, rabbit;
    public static boolean methodOfExhaustion(int head, int foot) {
        boolean result = false;

        int i, j;
        for (i = 0; i <= head; i++) {
            j = head - i;
            if (i * 2 + j * 4 == foot) {
                result = true;
                chicken = i;
                rabbit = j;
            }
        }

        return result;
    }

    public static void main(String[] args) {
        System.out.println("穷举法求解鸡兔同笼问题...");

        System.out.print("请输入头数:");
        Scanner input = new Scanner(System.in);
        int head = input.nextInt();
        System.out.print("请输入脚数:");
        int foot = input.nextInt();

        if (methodOfExhaustion(head, foot))
            System.out.println("鸡 " + chicken + " 只,兔 " + rabbit + " 只。");
        else
            System.out.println("无解。");
    }
}

在这里插入图片描述

2 递推算法

递推算法是很常用的算法思想,在数学计算等方面有着广泛的应用。递推算法适合有着明显公式规律的场合。

  • 递推算法基本思想

递推算法是一种理性思维模式的代表,其根据己有的数据和关系,逐步推导而得到结果。递推算法的执行过程如下:

  1. 根据已知结果和关系,求解中间结果。
  2. 判定是否达到要求,如果没有达到,则继续根据已知结果和关系求解中间结果;如果满足要求,则表示寻找到一个正确的答案。

递推算法往往需要用户知道答案和问题之间的逻辑关系。在许多数学问题中,都有着明确的计算公式可以遵循,因此往往可以采用递推算法来实现。
在这里插入图片描述

import java.util.Scanner;

public class RabbitLitter {
    static int fibonacci(int n) {
        if (n == 1 || n == 2) {
            return 1;
        } else {
            return fibonacci(n-1) + fibonacci(n-2);
        }
    }

    public static void main(String[] args) {
        System.out.println("递推算法求解兔子产仔...");

        System.out.print("请输入时间:");
        Scanner scanner = new Scanner(System.in);
        int month = scanner.nextInt();
        System.out.printf("经过 %d 月,共能繁殖 %d 对兔子\n", month, fibonacci(month));
    }
}

递推算法求解兔子产仔...
请输入时间:12
经过 12 月,共能繁殖 144 对兔子

Process finished with exit code 0

3 递归算法

import java.util.Scanner;

public class RecursiveAlgorithm {
    static long fact(int n) {
        if (n <= 1)
            return 1;
        else
            return n * fact(n - 1);
    }

    public static void main(String[] args) {
        System.out.println("递归算法求解阶乘...");

        System.out.print("请输入一个整数:");
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        System.out.printf("%d 的阶乘为 %d.\n", n, fact(n));
    }
}

递归算法求解阶乘...
请输入一个整数:12
12 的阶乘为 479001600.

Process finished with exit code 0

4 分治算法

在这里插入图片描述
在这里插入图片描述

import java.util.Scanner;

public class DivideAndConquerAlgorithm {
    static final int MAXCOINNUM = 30;

    static int falseCoin(int[] coin, int low, int high) {
        int sum1, sum2;
        sum1 = sum2 = 0;

        // 递归出口
        if (low + 1 == high) {
            if (coin[low] < coin[high]) {
                return low + 1;// 硬币序号比下标大 1
            } else {
                return high + 1;
            }
        }

        // 分解问题
        if ((high - low + 1) % 2 == 0) {// 当硬币个数为偶数
            for (int j = low; j <= low + (high - low) / 2; j++) {
                sum1 += coin[j];        // 前一半硬币的重量
            }
            for (int j = low + (high - low) / 2 + 1; j <= high; j++) {
                sum2 += coin[j];        // 后一半硬币的重量
            }
            if (sum1 > sum2)            // 假币在后一半中,在后一半中继续查找
                return falseCoin(coin, low + (high - low) / 2 + 1, high);
            else                        // 假币在前一半中,在前一半中继续查找
                return falseCoin(coin, low, low + (high - low) / 2);
        } else {                        // 当硬币个数为奇数
            for (int j = low; j <= low + (high - low) / 2 - 1; j++) {
                sum1 += coin[j];        // 前一半硬币的重量
            }
            for (int j = low + (high - low) / 2 + 1; j <= high; j++) {
                sum2 += coin[j];        // 后一半硬币的重量
            }
            if (sum1 > sum2) {          // 假币在后一半中,在后一半中继续查找
                return falseCoin(coin, low + (high - low) / 2 + 1, high);
            } else if (sum1 < sum2) {   // 假币在前一半中,在前一半中继续查找
                return falseCoin(coin, low, low + (high - low) / 2 - 1);
            } else {                    // 假币为中间那个硬币
                return low + (high - low) / 2 + 1;
            }
        }
    }

    public static void main(String[] args) {
        System.out.println("分治算法求假币问题...");

        int[] coin = new int[MAXCOINNUM];
        System.out.print("请输入硬币总个数:");
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        System.out.println("请逐个输入硬币重量(只能有一枚假币)...");
        for (int i = 0; i < n; i++) {
            coin[i] = scanner.nextInt();
        }
        System.out.printf("%d 个硬币中,第 %d 个硬币为假币。\n", n, falseCoin(coin, 0, n - 1));
    }
}

分治算法求假币问题...
请输入硬币总个数:13
请逐个输入硬币重量(只能有一枚假币)...
1 5 5 5 5 5 5 5 5 5 5 5 5
13 个硬币中,第 1 个硬币为假币。

Process finished with exit code 0

5 概率算法

在这里插入图片描述
在这里插入图片描述

import java.util.Scanner;

public class ProbabilityAlgorithm {
    static double MonteCarloPI(int n) {
        double PI, x, y;
        int sum = 0;
        for (int i = 0; i < n; i++) {
            x = Math.random(); // 产生 0~1 之间的一个随机数
            y = Math.random();
            // 点落在阴影区域
            if (x * x + y * y <= 1)
                sum++;
        }
        
        // π = 4 * 概率
        PI = 4.0 * sum / n;
        return PI;
    }

    public static void main(String[] args) {
        System.out.println("蒙特卡罗算法求 π ...");

        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入点的数量(数量越大,π 的值越精确):");
        int n = scanner.nextInt();
        double PI = MonteCarloPI(n);
        System.out.println("π = " + PI);
    }
}

蒙特卡罗算法求 π ...
请输入点的数量(数量越大,π 的值越精确):100000000
π = 3.14146396

Process finished with exit code 0
发布了50 篇原创文章 · 获赞 38 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42250302/article/details/104184784