经典算法的Java实现36题文档格式.docx

上传人:b****5 文档编号:18082024 上传时间:2022-12-13 格式:DOCX 页数:76 大小:183.62KB
下载 相关 举报
经典算法的Java实现36题文档格式.docx_第1页
第1页 / 共76页
经典算法的Java实现36题文档格式.docx_第2页
第2页 / 共76页
经典算法的Java实现36题文档格式.docx_第3页
第3页 / 共76页
经典算法的Java实现36题文档格式.docx_第4页
第4页 / 共76页
经典算法的Java实现36题文档格式.docx_第5页
第5页 / 共76页
点击查看更多>>
下载资源
资源描述

经典算法的Java实现36题文档格式.docx

《经典算法的Java实现36题文档格式.docx》由会员分享,可在线阅读,更多相关《经典算法的Java实现36题文档格式.docx(76页珍藏版)》请在冰豆网上搜索。

经典算法的Java实现36题文档格式.docx

publicvoidmove(intn,chara,charb,charc){

if(n==1)

System.out.println("

盘"

+n+"

由"

+a+"

移至"

+c);

else{

move(n-1,a,c,b);

System.out.println("

move(n-1,b,a,c);

}

}

(2)费式数列

Fibonacci为1200年代的欧洲数学家,在他的著作中曾经提到:

“若有一只免子每个月生一只小免子,一个月后小免子也开始生产。

起初只有一只免子,一个月后就有两只免子,二个月后有三只免子,三个月后有五只免子(小免子投入生产)......”。

如果不太理解这个例子的话,举个图就知道了,注意新生的小免子需一个月成长期才会投入生产,类似的道理也可以用于植物的生长,这就是Fibonacci数列,一般习惯称之为费氏数列,例如以下:

1、1、2、3、5、8、13、21、34、55、89......

依说明,我们可以将费氏数列定义为以下:

fn=fn-1+fn-2   

ifn>

2

fn=1      ifn=0,1 

实现:

//Java程序的实现:

publicclassFibonacci{

publicstaticvoidmain(String[]args){

int[]fib=newint[20];

fib[0]=0;

fib[1]=1;

for(inti=2;

i<

fib.length;

i++)

fib[i]=fib[i-1]+fib[i-2];

for(inti=0;

System.out.print(fib[i]+"

"

System.out.println();

}

(3)巴斯卡(Pascal)三角形

巴斯卡(Pascal)三角形基本上就是在解nCr,因为三角形上的每一个数字各对应一个nCr,其中n为row,而r为column,如下:

    0C0

1C01C1

2C02C12C2

 3C03C13C23C3

4C04C14C24C34C4

对应的数据如下图所示:

巴斯卡三角形中的nCr可以使用以下这个公式来计算,以避免阶乘运算时的数值溢位:

nCr=[(n-r+1)*nCr-1]/r

nC0=1 

//java实现

importjava.awt.*;

importjavax.swing.*;

publicclassPascalextendsJFrame{

publicPascal(){

setBackground(Color.white);

setTitle("

巴斯卡三角形"

setSize(520,350);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(700,700);

setVisible(true);

privatelongcombi(intn,intr){

inti;

longp=1;

for(i=1;

=r;

p=p*(n-i+1)/i;

returnp;

publicvoidpaint(Graphicsg){

g.setColor(Color.white);

g.clearRect(0,0,getSize().width,getSize().height);

g.setColor(Color.red);

finalintN=12;

intn,r,t;

for(n=0;

n<

=N;

n++){

for(r=0;

r<

=n;

r++)

g.drawString("

+combi(n,r),(N-n)*20+r*40,n*20+50);

publicstaticvoidmain(Stringargs[]){

Pascalfrm=newPascal();

(4)蒙地卡罗法求PI

蒙地卡罗为摩洛哥王国之首都,该国位于法国与义大利国境,以赌博闻名。

蒙地卡罗的基本原理为以乱数配合面积公式来进行解题,这种以机率来解题的方式带有赌博的意味,虽然在精确度上有所疑虑,但其解题的思考方向却是个值得学习的方式。

蒙地卡罗的解法适用于与面积有关的题目,例如求PI值或椭圆面积,这边介绍如何求PI值;

假设有一个圆半径为1,所以四分之一圆面积就为PI,而包括此四分之一圆的正方形面积就为1,如下图所示:

如果随意的在正方形中投射飞标(点)好了,则这些飞标(点)有些会落于四分之一圆内,假设所投射的飞标(点)有n点,在圆内的飞标(点)有c点,则依比例来算,就会得到上图中最后的公式。

至于如何判断所产生的点落于圆内,很简单,令乱数产生X与Y两个数值,如果X^2+Y^2等于1就是落在圆内。

//java程序实现

publicclassPI{

finalintN=50000;

intsum=0;

for(inti=1;

N;

i++){

doublex=Math.random();

doubley=Math.random();

if((x*x+y*y)<

1)

sum++;

PI="

+(double)4*sum/N);

(5)最大公因数、最小公倍数

最大公因数使用辗转相除法来求,最小公倍数则由这个公式来求:

GCD*LCM=两数乘积

publicclassGcdLcm{

publicstaticintgcdOf(intm,intn){

intr;

while(n!

=0){

r=m%n;

m=n;

n=r;

returnm;

publicstaticintlcmOf(intm,intn){

returnm*n/gcdOf(m,n);

publicstaticvoidmain(String[]args)throwsIOException{

BufferedReaderln=newBufferedReader(newInputStreamReader(System.in));

请输入第一个数:

intx=Integer.parseInt(ln.readLine());

请输入第二个数:

inty=Integer.parseInt(ln.readLine());

GCDof("

+x+"

"

+y+"

)="

+GcdLcm.gcdOf(x,y));

LCMof("

+GcdLcm.lcmOf(x,y));

(6)阿姆斯壮数

在三位的整数中,例如153可以满足13+53+33=153,这样的数称之为Armstrong数,试写出一程式找出所有的三位数Armstrong数。

Armstrong数的寻找,其实就是在问如何将一个数字分解为个位数、十位数、百位数......,这只要使用除法与余数运算就可以了,例如输入input为abc,则:

a=input/100

b=(input%100)/10

c=input%10

publicclassArmstrong{

寻找Armstrong数:

for(inti=100;

=999;

inta=i/100;

intb=(i%100)/10;

intc=i%10;

if(a*a*a+b*b*b+c*c*c==i)

System.out.print(i+"

}System.out.println();

(7)最大访客数

现将举行一个餐会,让访客事先填写到达时间与离开时间,为了掌握座位的数目,必须先估计不同时间的最大访客数。

这个题目看似有些复杂,其实相当简单,单就计算访客数这个目的,同时考虑同一访客的来访时间与离开时间,反而会使程式变得复杂;

只要将来访时间与离开时间分开处理就可以了,假设访客i的来访时间为x[i],而离开时间为y[i]。

在资料输入完毕之后,将x[i]与y[i]分别进行排序(由小到大),道理很简单,只要先计算某时之前总共来访了多少访客,然后再减去某时之前的离开访客,就可以轻易的解出这个问题

importjava.util.*;

publicclassMaxVisit{

publicstaticintmaxGuest(int[]x,int[]y,inttime){

intnum=0;

x.length;

if(time>

x[i])

num++;

y[i])

num--;

returnnum;

publicstaticvoidmain(String[]args)throwsIOException{

BufferedReaderbuf=newBufferedReader(newInputStreamReader(System.in));

输入来访时间与离开时间(0~24):

范例:

1015"

输入-1结束"

java.util.ArrayListlist=newArrayList();

while(true){

System.out.print("

>

Stringinput=buf.readLine();

if(input.equals("

-1"

))

break;

list.add(input);

int[]x=newint[list.size()];

int[]y=newint[list.size()];

Stringinput=(String)list.get(i);

String[]strs=input.split("

x[i]=Integer.parseInt(strs[0]);

y[i]=Integer.parseInt(strs[1]);

Arrays.sort(x);

Arrays.sort(y);

for(inttime=0;

time<

25;

time++){

System.out.println(time+"

时的最大访客数:

+MaxVisit.maxGuest(x,y,time));

(8)洗扑克牌(乱数排列)

洗扑克牌的原理其实与乱数排列是相同的,都是将一组数字(例如1~N)打乱重新排列,只不过洗扑克牌多了一个花色判断的动作而已。

初学者通常会直接想到,随机产生1~N的乱数并将之存入阵列中,后来产生的乱数存入阵列前必须先检查阵列中是否已有重复的数字,如果有这个数就不存入,再重新产生下一个数,运气不好的话,重复的次数就会很多,程式的执行速度就很慢了,这不是一个好方法。

以1~52的乱数排列为例好了,可以将阵列先依序由1到52填入,然后使用一个回圈走访阵列,并随机产生1~52的乱数,将产生的乱数当作索引取出阵列值,并与目前阵列走访到的值相交换,如此就不用担心乱数重复的问题了,阵列走访完毕后,所有的数字也就重新排列了。

至于如何判断花色?

这只是除法的问题而已,取商数判断花色,取余数判断数字,您可以直接看程式比较清楚。

publicclassShuffleCard{

finalintN=52;

int[]poker=newint[N+1];

//初始化阵列

poker[i]=i;

//洗牌

intj=(int)(Math.random()*N);

if(j==0)

j=1;

inttmp=poker[i];

poker[i]=poker[j];

poker[j]=tmp;

//判断花色

switch((poker[i]-1)/13){

case0:

System.out.print("

桃"

break;

case1:

心"

case2:

砖"

case3:

梅"

}

//扑克牌数字

intremain=poker[i]%13;

switch(remain){

K"

case12:

Q"

case11:

J"

default:

System.out.print(remain+"

break;

}

if(i%13==0)

(9)约瑟夫问题(JosephusProblem)

据说着名犹太历史学家Josephus有过以下的故事:

在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。

然而Josephus和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

约瑟夫问题可用代数分析来求解,将这个问题扩大好了,假设现在您与m个朋友不幸参与了这个游戏,您要如何保护您与您的朋友?

只要画两个圆圈就可以让自己与朋友免于死亡游戏,这两个圆圈内圈是排列顺序,而外圈是自杀顺序,如下图所示:

使用程式来求解的话,只要将阵列当作环状来处理就可以了,在阵列中由计数1开始,每找到三个无资料区就填入一个计数,直而计数达41为止,然后将阵列由索引1开始列出,就可以得知每个位置的自杀顺序,这就是约瑟夫排列,41个人而报数3的约琴夫排列如下所示:

1436138152243031634425175403161826737198352792032104121112839122233132923

由上可知,最后一个自杀的是在第31个位置,而倒数第二个自杀的要排在第16个位置,之前的人都死光了,所以他们也就不知道约琴夫与他的朋友并没有遵守游戏规则了。

publicclassJosephus{

publicstaticint[]arrayOfJosephus(intnumber,intper){

int[]man=newint[number];

for(intcount=1,i=0,pos=-1;

count<

=number;

count++){

do{

pos=(pos+1)%number;

//环状处理

if(man[pos]==0)

i++;

if(i==per){//报数为3了

i=0;

break;

}

}while(true);

man[pos]=count;

returnman;

}

publicstaticvoidmain(String[]args){

int[]man=Josephus.arrayOfJosephus(41,3);

intalive=3;

约琴夫排列:

41;

System.out.print(man[i]+"

\nL表示3个存活的人要放的位置:

if(man[i]>

(41-alive))

L"

else

D"

if((i+1)%5==0)

(10)排列组合

将一组数字、字母或符号进行排列,以得到不同的组合顺序,例如123这三个数的排列组合有:

123、132、213、231、312、321。

可以使用递回将问题切割为较小的单元进行排列组合,例如1234的排列可以分为1[234]、2[134]、3[124]、4[123]进行排列,这边利用旋转法,先将旋转间隔设为0,将最右边的数字旋转至最左边,并逐步增加旋转的间隔,例如:

1234->

旋转1->

继续将右边234进行递回处理

2134->

旋转12变为21->

继续将右边134进行递回处理

3124->

旋转123变为312->

继续将右边124进行递回处理

4123->

旋转1234变为4123->

继续将右边123进行递回处理

publicclassPermutation{

publicstaticvoidperm(int[]num,inti){

if(i<

num.length-1){

for(intj=i;

j<

=num.length-1;

j++){

inttmp=num[j];

//旋转该区段最右边数字至最左边

for(intk=j;

k>

i;

k--)

num[k]=num[k-1];

num[i]=tmp;

p

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 电力水利

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1