数据结构与算法--------Java实现(第三章 基本算法思想)

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.执行过程:

  1. 对于一个规模为N的问题,如果很容易解决,则直接解决,否则执行下面的步骤;
  2. 将问题N分解为M个规模较小的子问题,这些子问题之间是独立的,并且与原问题形式相同;
  3. 递归地解这些子问题;
  4. 将各个子问题的解合并得到原来问题的解。

3.算法实例

题目:一个袋子里有30枚硬币,其中一枚是假的,并且假的银币和真的硬币一模一样,肉眼和难分辨,目前只知道假币比真币轻一点。请问如何进行区分?

思路:采用递归分治思想进行求解:

  1. 首先为每一枚硬币编号,然后将所有的硬币等分为两份,放在天秤的两端。这样就将区分30枚硬币的问题变为区分两堆银币的问题;
  2. 因为假银币分量较轻,所以天秤较轻的一端一定含有假币;
  3. 再将较轻的一侧中的硬币分为两等份,重复上述的做法;
  4. 直到剩下最后两枚硬币,可用天秤直接找出来。

代码:

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.执行流程:

  1. 将问题转化为相应的几何图形S,S的面积是容易计算的,问题的结果往往对应几何中某一部分的面积;
  2. 然后,向集合中随机撒点;
  3. 统计几何图形S中和S1中的点数。根据S的面积和S1面积的关系以及各种图形中的点数来计算得到结果;
  4. 判断上述结果是否在需要的精度之内,如果未达到精度则继续执行步骤(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;
    }
}

代码可在我的Github下载:https://github.com/flakkaqi/DataStructure_and_Algorithms.git

发布了19 篇原创文章 · 获赞 13 · 访问量 7576

猜你喜欢

转载自blog.csdn.net/qisoft1213/article/details/86541958