递归:
阶乘:
import java.util.Scanner;
public class factorial {
public static int factorialdemo(int n)
{
if(n==0)return 1;
else return n*factorialdemo(n-1);
}
public static void main(String [] args)
{
Scanner sc = new Scanner(System.in);
int a=sc.nextInt();
int b=factorialdemo(a);
System.out.println(b);
sc.close();
}
}
输出结果:
(1)
(2)
(3)
结论:
显然输入的原数据越大,操作时间越长
分治:
概念:将一个规模较大的问题,分成k个子问题,分别求出每个子问题的解,合并起来就变成了原问题的解。每个子问题的规模要大致相当,这样效率最高
当规模为n时的时间效率:
二分检索法:
public static int BinarySearch(int[]a,int x,int n) {
int left=0;
int right=n-1;
while(left<=right)
{
int middle=(left+right)/2;
if(x==a[middle])return middle;
if(x>a[middle])left=middle+1;
else right=middle-1;
}
return -1;
}
public static void main(String [] args)
{
int i,j,k,f;
Scanner sc=new Scanner(System.in);
System.out.println("请输入母数组长度");
i=sc.nextInt();
int[]a=new int[i];
System.out.println("请输入母数组");
for(f=0;f<i;f++)
a[f]=sc.nextInt();
System.out.println("请输入要查找的元素");
j=sc.nextInt();
k=BinarySearch(a, j, i)+1;
if(k>0)
System.out.println("该元素在第"+k+"位上");
else
System.out.println("该元素不在数组中");
sc.close();
}
输出结果:
(1)处理内容较多时,查找时间差距较大
时间效率最好结果:
时间效率最坏结果:
(2)处理内容较少时,查找时间差距不大
时间效率最好结果:
时间效率最坏结果:
大整数的乘法:
设X,Y都是n位的二进制整数,计算XY,直接每位相乘需要进行O()步运算,使用大整数乘积算法,可大大节省运算时间
原来
时间效率为
现将XY改写为,则现在只需要计算三次n/2位整数的乘法【AC,BD,(A-B)(D-C)】
此时时间效率为
大大减少了运算次数
Strassen矩阵乘法:
定义矩阵,计算的时间效率为O(
),设n为2的幂,A,B,C都可分成4个(n/2)*(n/2)的方阵,通过计算8个n/2阶方阵的乘积和4个n/2阶方阵的加法,时间效率为
该方法并没有提高效率,本质原因是没有减少乘法运算次数。Strassen提出了一种新算法,只用7次乘法,但增加了加减次数,运算方法如下
时间效率为
计算时间复杂性有较大提升
棋盘覆盖:
在一个(k>=0)方格组成的棋盘中,只有一个特殊方格和其他方格不同,特殊方格在棋盘上有
种情况,用L型骨牌覆盖除特殊方格外所有方格,且不能重叠,有
个骨牌,当k>0时,将棋盘分为四个
子棋盘,特殊方格必位于四个子棋盘之一中,用一个L型骨牌覆盖这三个字棋盘会和处,这样被L型骨牌覆盖的方格就成为该子棋盘中的特殊方格,就将原问题转化为四个规模较小的子问题,递归分割,直到棋盘简化为1*1的棋盘,问题就解决了
代码实现:
public void chessBoard(int tr/*棋盘左上角方格行号*/,int tc/*棋盘左上角方格列号*/,int dr/*特殊方格行号*/,int dc/*特殊方格列号*/,int size/*棋盘规格 */)
{
int [][] board=new int [tr][tc];
int tile=0;
if(size==1)return;
int t=tile++,//L型骨牌牌号
s=size/2;//分割棋盘
//覆盖左上棋盘
if(dr<tr+s&&dc<tc+s)//特殊方格在此棋盘中
chessBoard(tr,tc,dr,dc,s);
else//此棋盘中无特殊方格
{
board[tr+s-1][tc+s-1]=t;//用t号L型骨牌覆盖右下角
chessBoard(tr,tc,tr+s-1,tc+s-1,s);//覆盖其余方格
}
//覆盖右上棋盘
if(dr>=tr+s&&dc<tc+s)
chessBoard(tr,tc+s,dr,dc,s);
else
{
board[tr+s-1][tc+s]=t;//用t号L型骨牌覆盖左下角
chessBoard(tr,tc+s,tr+s-1,tc+s,s);
}
//覆盖左下棋盘
if(dr>=tr+s&&dc>=tc+s)
chessBoard(tr+s,tc,dr,dc,s);
else
{
board[tr+s][tc+s-1]=t;//用t号L型骨牌覆盖右上角
chessBoard(tr+s,tc,tr+s,tc+s-1,s);
}
//覆盖右下棋盘
if(dr>=tr+s&&dc>=tc+s)
chessBoard(tr+s,tc+s,dr,dc,s);
else
{
board[tr+s][tc+s-1]=t;//用t号L型骨牌覆盖左上角
chessBoard(tr+s,tc+s,tr+s,tc+s-1,s);
}
主函数:
public static void main(String[]arg)
{
int rd,cd,size;
System.out.println("请输入棋盘大小[应满足log2(size)为整数]");
Scanner sc=new Scanner(System.in);
size=sc.nextInt();
int [][]chess=new int[size][size];
System.out.println("请输入特殊方格位置");
rd=sc.nextInt();
cd=sc.nextInt();
chess[rd][cd]=-1;
chessBoard(0, 0, rd, cd, size,chess);
System.out.println("棋盘:");
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
System.out.print(chess[i][j]+"\t");
System.out.println();
}
sc.close();
}
输出结果:
(1)数据量较小
(2)数据量较大
T(k)是该算法覆盖一个棋盘所需时间
T(k)=O(),该算法是一个在渐进意义下最优的算法
总结:
错误:
(1)System.out.println()输出一个结果占据一整行,如需多个数据输出在同一行,需用System.out.print()(与C++相似)
(2)java与C++区别之一是:java每个编写程序都必须规定其公用public(只有公用的数据可以在其他的程序中使用),或私有private属性(其他程序不能使用);
java中输入Scanner sc = new Scanner(System.in);int a=sc.nextInt();将输入的值赋给a
C++中输入cin>>a;
java中输出System.out.println("用时"+time+"纳秒");
C++中输入cout<<a;
(3)计时操作:
用long millis1=System.nanoTime()放在操作之前,该语句可获取当前的时间(精确到纳秒),将long millis2=System.nanoTime();放在操作之后,再次获取一个时间,最后两时间相减long time=millis2-millis1;就可以得到进行操作运算的具体时间
总结:
学习了java的基础编写,并在VScode上运用和熟悉相关操作,体会了各编写语言之间的差异。学习了java中递归的概念操作,和部分分治策略的编写思路