Java数据结构和算法-八皇后、约瑟夫杀人法、大数相乘

回溯法:

回溯法(英语:backtracking)也称试探法,回溯法有“通用的解题方法”之称。它可以系统的搜索一个问题的所有解或者任意解。

回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点

出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过

对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。

回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,

只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较

大的问题。

回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两种情况:

1 .找到一个可能存在的正确的答案。

2. 在尝试了所有可能的分步方法后宣告该问题没有答案。

在最坏的情况下,回溯法会导致一次复杂度为指数时间的计算。

回溯法-八皇后问题:

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

可能是最好的八皇后问题博客:http://www.cnblogs.com/newflydd/p/5091646.html

package com.algorithm.queen;

import java.util.Date;


/**
 * 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,
 * 即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
 * 下面使用递归方法解决
 *
 */
public class EightQueen {
    private static final short N=16;        //使用常量来定义,方便之后解N皇后问题
    private static int count=0;            //结果计数器

    public static void main(String[] args) {
        Date begin =new Date();
        //初始化棋盘,全部置0
        short chess[][]=new short[N][N];
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                chess[i][j]=0;
            }
        }

        putQueenAtRow(chess,0);
        Date end =new Date();
        System.out.println("解决 " +N+ " 皇后问题,用时:" +String.valueOf(end.getTime()-begin.getTime())+ "毫秒,计算结果:"+count);
    }

    private static void putQueenAtRow(short[][] chess, int row) {
        /**
         * 递归终止判断:如果row==N,则说明已经成功摆放了8个皇后
         * 输出结果,终止递归
         */
        if(row==N){
            count++;
            System.out.println("第 "+ count +" 种解:");
            for(int i=0;i<N;i++){
                for(int j=0;j<N;j++){
                    System.out.print(chess[i][j]+" ");
                }
                System.out.println();
            }
            return;
        }

        short[][] chessTemp=chess.clone();

        /**
         * 向这一行的每一个位置尝试排放皇后
         * 然后检测状态,如果安全则继续执行递归函数摆放下一行皇后
         */
        for(int i=0;i<N;i++){
            //摆放这一行的皇后,之前要清掉所有这一行摆放的记录,防止污染棋盘
            for(int j=0;j<N;j++){
                chessTemp[row][j]=0;
            }
            chessTemp[row][i]=1;

            if( isSafety( chessTemp,row,i ) ){
                putQueenAtRow(chessTemp,row+1);
            }
        }
    }

    private static boolean isSafety(short[][] chess,int row,int col) {
        //判断中上、左上、右上是否安全
        int step=1;
        while(row-step>=0){
            if(chess[row-step][col]==1)                //中上
                return false;
            if(col-step>=0 && chess[row-step][col-step]==1)        //左上
                return false;
            if(col+step<N && chess[row-step][col+step]==1)        //右上
                return false;

            step++;
        }
        return true;
    }
}

约瑟夫杀人法:

约瑟夫将军抓到一群俘虏,需要剩下一个人回去给敌军报信。让俘虏围成一圈,从1数数,数到某个数时,杀掉一个人,重新开始从1数数。直到剩下一个人。

约瑟夫杀人法Java实现:

package com.algorithm.joseph;

public class Joseph {
    private static int MAXNUM=20;
    private static int NUM=5;

    class Node{
        private int value;
        private Node nextNode;

        public Node(int value){
            this.value=value;
        }

    }
    public void killNode(){
        //建立循环单链表
        Node head=new Node(1);
        Node x=head;
        for(int i=2;i<=MAXNUM;i++){
             x.nextNode=new Node(i);
             x=x.nextNode;
        }
//        head=x.nextNode;注意顺序,报错
        x.nextNode=head;

        while(x!=x.nextNode){
            //x在20的位置
            for(int i=1;i<NUM;i++){
                x=x.nextNode;
            }
            System.out.println("被干掉的:"+x.nextNode.value);
            x.nextNode=x.nextNode.nextNode;
        }
        System.out.println("最后的幸运儿是:"+x.value);

    }

    public static void main(String[] args) {
        Joseph joseph=new Joseph();
        joseph.killNode();
    }


}
输出:
被干掉的:5
被干掉的:10
被干掉的:15
被干掉的:20
被干掉的:6
被干掉的:12
被干掉的:18
被干掉的:4
被干掉的:13
被干掉的:1
被干掉的:9
被干掉的:19
被干掉的:11
被干掉的:3
被干掉的:17
被干掉的:16
被干掉的:2
被干掉的:8
被干掉的:14
最后的幸运儿是:7

大数相乘:

所谓大数相乘(Multiplication algorithm),就是指数字比较大,相乘的结果超出了基本类型的表示范围,所以这样的数不能够直接做乘法运算。

大数相乘Java实现:

package com.algorithm.bigcount;

/**
 * 大数相乘:将较大数字相乘转化为字符串和数组处理。
 */
public class BigCountMultiply {
    public static void main(String[] args) {
        String str1="753656566859769";
        String str2="9518598598486568654";
        //字符串反转,希望后面生成的数组位置0对应个位,位置1对应十位,位置2对应百位.....
        str1=reserve(str1);
        str2=reserve(str2);

        int len1=str1.length();
        int len2=str2.length();
        int len=len1+len2+3;
        char[] chars=new char[len];

        char[] chars1=str1.toCharArray();
        char[] chars2=str2.toCharArray();

        int a[]=new int[len1];
        int b[]=new int[len2];
        int c[]=new int[len];

        for(int i=0;i<len1;i++){
            a[i]=Integer.valueOf(String.valueOf(chars1[i]));
        }
        for(int i=0;i<len2;i++){
            b[i]=Integer.valueOf(String.valueOf(chars2[i]));
        }
        countMultiply(c,a,b,len,len1,len2);

    }

    private static void countMultiply(int[] c, int[] a, int[] b, int len, int len1, int len2) {
        for(int i=0;i<len1;i++){
            for(int j=0;j<len2;j++){
                //核心代码:相乘结果各个位置上的值和乘数对应的位置有关联。例如:结果个位上的数值只能由乘数个位上的数相乘取个位。
                c[i+j]+=a[i]*b[j];
            }
        }
        for(int i=0;i<len;i++){
            if(c[i]/10>0){//判断是否需要进位
                //更高位置进位
                c[i+1]+=c[i]/10;
            }
            //取该位置对应数字
            c[i]=c[i]%10;
        }
        int m=0;
        for(int i=len-1;i>=0;i--){
            //数组下标对应较高位置,即结果较高位数可能有多个0,不需要遍历应去除
            if(c[i]>0){
               m=i;
               break;
            }
        }
        //从结果最高不为0位置开始遍历
        for(int i=m;i>=0;i--){
            System.out.print(c[i]);
        }

    }

    private static String reserve(String str1) {
        if(str1==null||str1.length()==1){
            return str1;

        }else {
            return reserve(str1.substring(1))+str1.charAt(0);
        }
    }


}
输出:7173754341051596127319080809080926

猜你喜欢

转载自blog.csdn.net/Colin_Qichao/article/details/81538327
今日推荐