1、打印汉诺塔(递归法思想)的步骤:
import java.util.Scanner;
/*
汉诺塔————要求:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。
操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,
小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
在整个过程中具体所要注意的事项是:
1、有三根柱子,分别为:A(起始柱)、B(辅助柱)、C(目标柱)
2、A柱上拥有64个盘子,一次是从下到上,从大到小(即大盘在下面,小盘在上面)
3、每一次只能移动一个盘子,并且每一根柱上都得是大盘在下,小盘在上
4、最终把A柱上的盘子全部移动到C柱上
先用三个盘分析一下思路:
再分析思路之前先介绍一下递归,什么是递归?
递归算是一种解题的思想,就是把大问题化小,再把小的问题合并成最终所想要的结果。例:形如下面二叉树
9
4 5
1 3 2 3
1 2 1 1 1 2
·······
2——(1,1)
3——(1,2)
4——(1,3)
1
9——(4,5)
2——(1,1)
5——(2,3) 1
3——(1,2)
2——(1,1)
先是由大到小一层的一层分,之后又从小返回到大,整个过程就叫做递归。
具体思路:
1、先是给A柱上放三个盘子,标号为1(顶层)、2(中层)、3(底层),刚好符合从大到小;
2、再把1和2看成一个整体,因此A柱上的盘子就有两个,(1,2)(顶层)、3(底层);
3、先把(1,2)盘移到B柱上,再把3移到C柱上;
4、这下把(1,2)又分开,就成了1、2,并且都在B柱上,现在又把1移到A柱上;
5、再把2移到C柱上,再把最后一个盘子1移到C柱上,目标达成。
如果为64个盘子运用递归的思想————先把前面63个看成一个整体,64因此就被分为两个部分,接着把63又分为两个部分,前62个盘子和63,
以此类推。
具体实现步骤如下:
*/
class Test02{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.print("请输入层数n:");
int n=input.nextInt();
System.out.print("请输入A、B、C:");
String str1=input.next();
String str2=input.next();
String str3=input.next();
hanNuo(n,str1,str2,str3);
}
public static void hanNuo(int n,String str1,String str2,String str3){
if(n==1){
System.out.println(str1+"->"+str3);
}else{
hanNuo(n-1,str1,str3,str2);
System.out.println(str1+"->"+str3);
hanNuo(n-1,str2,str1,str3);
//System.out.println(str2+"->"+str3);
}
}
}
2、for循环
/*
题目要求:总共打印8行,用五行分析一下解题思路吧;打印如下图形:
空格数:1 2 3 4
1 1
1 2 1 2
1 2 4 2 1 3
1 2 4 8 4 2 1 4
1 2 4 8 16 8 4 2 1 5
........
经上面的分析可得:该图形总共有5行: ————每一行由空格和具体的数字组成。
空格数是随着行数的增加而减一,因此该代码可写成:
for(int i=1;i<=5;i++){//i表示的是所打印的行数
for(int k=1;k<=5-i;k++){//k表示所打印的空格数
System.out.print(" ");
}
}
由上面可知,每一行的空格已打印,但是每一行的数字存在什么规律,以及每一行数字所要打印的个数:
1 2 3 4
1 1 1
2 1 2 1 2
3 1 2 4 2 1 3
4 1 2 4 8 4 2 1 4
5 1 2 4 8 16 8 4 2 1 5
2^0 2^1 2^2 2^3 2^4 2^3 2^2 2^1 2^0
-4 -3 -2 -1 0 1 2 3 4 x-(0) 1
x-(-1~1) 3
x-(-2~2) 5
x-(-3~3) 7
x-(-4~4) 9
........
因此由上面分析得每一行所打印数字的个数为1-i ~ i-1
并且每一行随打印的数值都是2的次幂,次幂的规律而是从0~4~0
第五行———— 所对应的坐标的绝对值与行数差了一个1
第四行———— 所对应的坐标的绝对值与行数差了一个1
第三行———— 所对应的坐标的绝对值与行数差了一个1
.......以此类推
因此在坐标的绝对值的基础上再加一个1与行数相等,正它们的差刚好是所对应每一行所要打印的第一个数值的次幂数,即2^(坐标的绝对值的基础上再加一个1与行数的差)
------因此代码可写为:
for(int m=1-i;m<=i-1;m++){
System.out.print(Math.abs(m)+1);
}
[注:再下来就是格式的要求——由于每一行所打印的最高位数值所占的大小为三个空格大小,因此就有输出的格式要求——————代码就可改为:
System.out.printf("%3.0f",Math.pow(2,i-1-Math.abs(k)));
特别提醒:为什么格式输出是%3.0f,因为Math.pow()——所执行的结果直接为double型,所以为%f,至于4,就是所输出的值所占的空格大小。
]
最后如果改成输入多少行就打印多少行,则只需改代码中的数字五变成一个变量。
*/
class Demo16{
public static void main(String[] args){
for(int i=1;i<=5;i++){//i表示的是行数
for(int j=1;j<=5-i;j++){
System.out.print(" ");
}
for(int k=1-i;k<=i-1;k++){
System.out.printf("%4.0f",Math.pow(2,i-1-Math.abs(k)));
}
System.out.println();
}
}
}
3、while循环
import java.util.Scanner;
/*
当输入若干个数字时,在内存中的调用机制————例:
输入的数字为:1 2 3 4 5 6 0
nextDouble();———下一个为1
1
nextDouble();———下一个为2
2
nextDouble();———下一个为3
3
nextDouble();———下一个为4
4
nextDouble();———下一个为5
5
nextDouble();———下一个为6
6
nextDouble();———下一个为0
0————表示的是循环结束的条件
对于当输入的数字存放在所定义的num中时————int num=nextInt();
nextInt();表示的是存放下一个数字
当用户输入入若干个数字时,这些数字先存放在一个临时存储区,等待被调用
因此对于While循环来说——形如:
System.out.print("Enter an integer,the input ends if it is 0:");
while(true){
double num=input.nextDouble();
if(num==0){
break;
}
}
运行过程如下:
先是num=1; 与0做判断,如果等于0,跳出循环,否则num=2;再判断,以此类推。
*/
class Demo11{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
int pos=0;//存放的是大于0的数
int neg=0;//存放的是小于0得数
double sum=0;//求和
System.out.print("Enter an integer,the input ends if it is 0:");
while(true){
double num=input.nextDouble();
if(num!=0){
sum+=num;
if(num>0){
pos++;
}else{
neg++;
}
}else{
break;
}
}
System.out.println("The number of positives is "+pos);
System.out.println("The number of negatives is "+neg);
System.out.println("The total is "+sum);
System.out.println("The average is "+sum/(pos+neg));
}
}
import java.util.Scanner;
/*
题目的要求是:求一元二次方程的根
第一步确定一元二次方程的表达式:a*x^2+b*x+c=0
第二步确定一元二次方程跟的情况
第三步:判断,判断的条件为——b*b-4*a*c
第四步:如果判断的条件大于0,有两个根
小于0,无实数解
等于0,有两个相同的解
第五步:编写代码
*/
class Demo01{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.print("Enter a, b, c:");//输入一元二次方程的三个参数
double a=input.nextDouble();
double b=input.nextDouble();
double c=input.nextDouble();
double x,y;//两个未知变量
/*
if-else语句
*/
if((b*b-4*a*c)>0){
x=(-b+Math.pow((b*b-4*a*c),0.5))/2*a;
y=(-b-Math.pow((b*b-4*a*c),0.5))/2*a;
System.out.println("x=" + x + " , " + "y=" + y);
} else if((b*b-4*a*c)==0){
x=(-b+Math.pow((b*b-4*a*c),0.5))/2*a;
y=x;
System.out.println("x=" + x + " , " + "y=" + y);
}else{
System.out.println("无实数解");
}
}
}
import java.util.Scanner;
/*
题目要求:采拳游戏
石头 0 剪刀 1 布 2
系统产生的随机数——————调用数学函数Math.random();该函数产生的是0到1.0的随机数,而且默认的是double型
因此必须得强制进行数据类型的转化
第一步:确定用户赢的可能————用户赢
用户0 系统1
用户1 系统2
用户2 系统0
第二步:如果用户与系统相同——————平手
第三步:其余系统赢
第四步:编写代码
*/
class Demo06{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
//系统所产生的随机数
int count=0;
while(true){
System.out.print("scissor(0) ,rock(1) ,paper(2):");
int num1=input.nextInt();
int num2=(int)(Math.random()*3);
if(num1
import java.util.Scanner;
/*
题目要求:构造一个函数,并调用该函数打印如下图案:
1 2 3
1 1
2 1 2
3 2 1 3
4 3 2 1 4
···· 1 ·
·
·
n
第一步:提示用户输入一个n ·
第二步:确定构造函数所要执行什么样的功能,根据题目的要求——
可得,该题目所需要的构造函数做执行的功能是上述图案
第三步:先打印前四行,由图案可知每一行是由空格和数值所组成,并且
每一行的空格数随着行的增加而减少,并且每一行的第一个数字一行数一样
因此:
for(int i=1;i<=n;i++){
for(int j=1;j<=n-i;j++){
System.out.print(" ");
}
for(int k=i;k>=1;k--){
System.out.print(k+" ");
}
System.out.println();
}
*/
class Demo03{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.print("请用户输入一个数num:");
int num=input.nextInt();
displayPattern(num);
}
public static void displayPattern(int n){
for(int i=1;i<=n;i++){
for(int j=1;j<=n-i;j++){
System.out.print(" ");
}
for(int k=i;k>=1;k--){
System.out.print(k+" ");
}
System.out.println();
}
}
}
4、斐波那契数列(迭代思想)
import java.util.Scanner;
class Test05{
/*
用迭代的思想打印斐波那契数列
首先明确斐波那契数列是形如怎样的数列?
1 1 2 3 5 8 13 21 ···
该数列具有怎样的规律:
从该数列的第三个数值开始,下一个位置上的数值是前两个数值之和
迭代思想具体体现在哪儿?
比如:先定义三个变量——a、b、c
a——用来存放该数列的第一个数值
b——用来存放该数列的第二个数值
c——用来存放前两个数值之和
这样才能出现前三个数值,那后面的该怎样办?明知道是一个循环,那么该循环体是什么?
已经定义了三个变量,并已经知道三个变量的含义
因此循环体——在进行第四个数值打印时——将:a=b;b=c;c=a+b;
所以这种思想就是迭代思想——代码如下:
*/
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.print("请输入想打印斐波那契数列的个数n:");
int n=input.nextInt();
int count=0;//记录个数
int a=1;
System.out.print(a+" ");
count++;
int b=1;
System.out.print(b+" ");
count++;
int c;
while(true){
c=a+b;//得出斐波那契数列中的数值
System.out.print(c+" ");
count++;
/*
迭代思想
*/
a=b;
b=c;
/*
终止条件
*/
if(count==n){
break;
}
}
}
}
5、数组的查找(主要二分法查找)
import java.util.Scanner;
/*
所谓查找,不明思议就是在一组数据中查找某一个值(大多情况下就是定义一个数组,在给定某一个值,进行查找),
而且查找的结果就只有两种,一、true;二、false
具体查找的方法都有哪些?——一般就是将给定的一组数据,从第一个遍历到所要查找的数值之后结束
并打印自己所查找的结果,对于初学者估计有很大的帮助,便于理解。
但是该方法的规模呈线性增长,当一组数据足够多时,岂不是规模越大,时间复杂度就越大
二——接下来这一种算法就是二分法:
二分法应该不陌生吧,不明思议就是对半查找,但是二分法查找是有一定的前提:就是该数据必须呈一种
升序或者降序
例如:在下面的一组数据中查找7
编号: 0 1 2 3 4 5 6
1 3 5 7 9 12 34 该数据总共为6个
查找的第一步:首先把该数据分成两部分——
0 1 2
第一步分为:1 3 5
3 4 5 6
第二部分为:7 9 12 34
查找的第二部:比较所要查的数值(7)与(该组数据的最小下标与最大下标之和再整除2的值)
查找的第三步:如果大于在第二部分里面在找,如果小于就在第一部分里面查找;
查找的第四部:7大于该值,因此在第二部分,所以再把第二部分数据分为两个部分——
3 4
第一部分:7 9
5 6
第二部分:12 34
查找的第五步:重复第二步,第三步
查找的第六步:最终找到在下标为3处所对应的值是7
总结:二分查找虽然过程能麻烦一点,但是规模较小于第一种方法,该方法的时间复杂度为logn
等其它查找方法
在查找的整个过程中会遇到,排序问题:我先介绍一下冒泡排序:
例:给定一组数据要求为升序:
1 3 2 7 4 总共为6个数字
具体的排序思路如下:
第一步:0 1 2 3 4
1 3 2 7 4 先是进行0和1进行比较:1小于3,则不动,再进行3和2比较,3大于2,3与2交换位置
以此类推,因此第一次所得结果为:1 2 3 4 7,结束
*/
class Test03{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.print("请输入一串数字:");
int[] arr=new int[10];
int count=0;
int temp=1;
while(true){
arr[count++]=input.nextInt();
if(count==10){
break;
}
}
for(int i=0;iarr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for(int i=0;iarr[mid]){
min=mid+1;
mid=(min+max)/2;
}else if(nummax){
System.out.println(index);
break;
}
}
}
}
六、数组的排序问题
class Test02{
public static void main(String[] args){
int[] arr1=new int[]{1,3,2,7,4,6,8,5,9};
int[] arr2=new int[]{1,3,2,7,4,6,8,5,9};
int[] arr3=new int[]{1,3,2,7,4,6,8,5,9};
int[] arr4=new int[]{1,3,2,7,4,6,8,5,9};
int temp=0;
/*
选择排序————具体通过一组数据来说明什么是选择排序?定义一个一位数组
a[]={1,3,2,7,4,6,8,5,9};
要求是:按升序排列
数组的下标: 0 1 2 3 4 5 6 7 8
1 3 2 7 4 6 8 5 9
首先先具体分析一下整个选择的过程:
第一次:
数组的下标: 0 1 2 3 4 5 6 7 8
1 3 2 7 4 6 8 5 9
首先是数组中a[0]与a[1]先比较,如果大于,两个数字交换,否则进行a[0]与a[2]比较
,如果大于,两个数交换,否则继续,以此类推,因此第一次比较的结果为:
1 3 2 7 4 6 8 5 9
第二次:
首先是数组中a[1]与a[2]比较,如果大于,两个数交换,否则进行a[1]与a[3]比较,
如果大于,两个数进行交换,否则继续,以此类推,因此第三次比较的结果为:
1 2 3 7 4 6 8 5 9
第三次:1 2 3 7 4 6 8 5 9
第四次:1 2 3 4 7 6 8 5 9
第五次:1 2 3 4 5 7 8 6 9
第六次:1 2 3 4 5 6 8 7 9
第七次:1 2 3 4 5 6 7 8 9
第八次:1 2 3 4 5 6 7 8 9
整个过程就是选择排序。
*/
for(int i=0;iarr1[j]){
temp=arr1[i];
arr1[i]=arr1[j];
arr1[j]=temp;
}
}
}
System.out.print("选择排序:");
for(int i=0;iarr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
System.out.print("冒泡排序:");
for(int i=0;iarr[j+1]){
arr[j]=arr[j+1];
}
else{
arr[j]=temp;
temp=arr[j+1];
}
}
arr[arr.length-i-1]=temp;
}
System.out.print("冒泡排序的优化:");
for(int i=0;i=1;j--){
if(arr[j]max){
max=arr[i];
}
if(arr[i]