JAVA基础:多重循环、方法、递归 (习题笔记)
一,编码题
1.打印九九乘法表
import java.util.*;
public class PanTi {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
for (int i = 0; i <= 9; i++) {//i控制行数
/* System.out.println("。\t。\t。\t。\t。\t。\t。\t。\t。");*/
for (int j = 1; j <= i; j++) {//j控制每行中的个数
System.out.print(i + "*" + j + "=" + (i * j) + "\t");//不换行打印数据
}
System.out.println();//打印完一行换行
}
}
}
2.判断1-100之间有多少个素数并输出所有素数。(将判断一个数是否是素数的功能提取成方法,在循环中直接调用即可)
import java.util.*;
public class PanTi {
public static void main(String[] args) {
int count = 0;
for (int j = 1; j <= 100; j++) {
if (isPrime(j)) {
System.out.print(j + " ");
count++;
if (count % 8 == 0) {
System.out.println();
}
}
}
}
private static boolean isPrime(int n) {
boolean flag = true; // flag:返回值默认true,表示是素数
if (n == 1)
flag = false;
else {
for (int i = 2; i <= Math.sqrt(n); i++) {
//Math.sqrt(n) 是 Java 中的一个静态方法,用于计算给定数值 n 的平方根
if (n % i == 0) {
flag = false;
break;
}
}
}
return flag;
}
}
3.输入三个班,每班10个学生的成绩,求和并求平均分
import java.util.*;
public class PanTi {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for(int i = 1;i<=3;i++){
//输入每个班成绩并求和
System.out.println("请输入第"+i+"个班的成绩");
double sum = 0;
for(int j=0;j<10;j++){
System.out.println(" 请输入第"+(j+1)+"个学生成绩:");
double score = sc.nextDouble();
System.out.println(score);
sum += score;
}
//求平均分
double avg = sum / 10;
//输出结果
System.out.println("第"+i+"个班学生总分:"+sum+" 平均分:"+avg); }
}
}
4.编写递归算法程序:一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求数列的第40位数是多少。
import java.util.*;
public class PanTi {
public static void main(String[] args) {
System.out.println(sum(40));
}
public static long sum(int n) {
if (n <= 0) {
return 0;
} else if (n == 1 || n == 2) {
return 1;
} else {
return sum(n - 1) + sum(n - 2);
}
}
}
(选)
1.打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个"水仙花数",因为153=1的三次方+5的三次方+3的三次方。
import java.util.*;
public class PanTi {
public static void main(String[] args) {
for(int i=100;i<1000;i++){
if(isLotus(i))
System.out.print(i+" ");
}
System.out.println();
}
//判断水仙花数
private static boolean isLotus(int lotus){
boolean flag=false;
int a = lotus % 10;//个位
int b = lotus / 10 % 10;//十位
int c = lotus / 100 % 10;//百位
if (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3) == lotus) {
//Math.pow(a, 3) 是 Java 中的一个静态方法,用于计算给定数值 a 的立方(即 a 的三次方)。
//返回值类型为 double
flag = true;
}
return flag;
}
}
2.定义方法:打印指定行和列的矩形
import java.util.*;
public class PanTi {
public static void main(String[] args) {
// 调用printStr方法
printStr(5, 4, "*");
}
public static void printStr(int rows, int columns, String str) {
for (int i = 0; i < rows; i++) {//行数
for (int j = 0; j < columns; j++) {//列数
System.out.print(str);//直接打印
}
System.out.println();//一行打完换行输出
}
}
}
3.编写Java程序,实现接收用户输入的正整数,输出该数的阶乘。要求:限制输入的数据在1-10之间,无效数据进行提示,结束程序。要求使用递归和循环分别实现。输出结果如:4!=1*2*3*4=24
import java.util.*;
public class PanTi {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//输入一个数
System.out.println("请输入你要判断的数据:");
int n = input.nextInt();
if(n>10 || n<1){
System.out.println("限制输入的数据在1-10之间");
System.exit(0);
}
String str = testString(n);
long sum = factRec(n);//递归
System.out.println(n+"!="+str+"="+sum);
long sum2 = factfor(n);//for循环
System.out.println(n+"!="+str+"="+sum2);
}
//实现字符串的输出
public static String testString(int n){
String result = "";
for (int i=1;i<=n;i++){
result +=(i+"*");
}
return result.substring(0, result.length()-1);
//substring() 是 Java 中 String 类的一个方法,用于获取字符串的一部分
//第一个参数 0 表示子字符串的起始索引。
//第二个参数 result.length() - 1 表示子字符串的结束索引(不包括该索引位置的字符)
}
//递归实现
public static long factRec(int n){
if(n==1){
return 1;
}else{
return n*factRec(n-1);
}
}
//for循环实现
public static long factfor(int n){
int sum = 1;
for (int i = 1; i < n; i++) {
sum += sum * i;
}
return sum;
}
}
4,请使用递归算法计算 n!
/**
* 请使用递归算法算法计算n!
*
* @param args
*/
public static void main(String[] args) {
System.out.println("请输入数字:");
Scanner input = new Scanner(System.in);
int n = input.nextInt();
long sum = method(n);
String str = method2(n);
System.out.println(n + "!" + "=" + str + "=" + sum);
}
public static String method2(int n) {
String result = "";
for (int i = 1; i <= n; i++) {
result += (i + "*");
}
return result.substring(0, result.length() - 1);
}
public static int method(int n) {
if (n == 1) {
return 1;
} else {
return n * method(n - 1);
}
}
二,简答题
1.在多重循环中,如何在内层循环中使用break跳出外层循环
在多重循环中,可以使用带有标签的break语句跳出外层循环。 在内层循环中使用break语句时,加上外层循环的标签即可实现跳出外层循环的功能。
具体步骤如下:
- 在需要跳出的外层循环之前,给外层循环添加一个标签,例如 outer_loop:。
- 在内层循环中使用 break outer_loop; 语句,即可跳出外层循环。
注意事项:
使用带有标签的break语句虽然可以跳出多层循环,但容易导致代码结构混乱,建议尽量避免嵌套过多的循环。
2.方法重载的定义、作用和判断依据
-
方法重载的定义:
方法重载是指在同一个类中可以定义多个方法,这些方法具有相同的名称但参数不同。参数的不同可以体现在类型、个数或顺序上。返回值类型和访问修饰符不影响方法的重载。
-
方法重载的作用:
通过方法重载,可以用同一个方法名实现多个功能相似的操作,只需传递不同的参数即可执行不同的逻辑。这提高了代码的重用性和可读性,使得代码更加简洁和易于维护。
-
方法重载的判断依据:
判断一个类中的多个方法是否构成重载,主要依据是方法名是否相同,参数的类型、个数或顺序是否不同。返回值类型和访问修饰符不作为判断依据
3.递归的定义和优缺点
-
递归的定义:
递归是一种函数或过程在其定义中调用自身的方法。 递归通常用于解决可以将问题分解为更小、更简单的子问题的情况。
递归的核心在于将一个大问题分解成多个小问题,而这些小问题又与原问题相似,直到达到一个简单的情况可以直接解决为止。
-
递归的优点:
(1)简洁性:
递归可以用较少的代码实现复杂的功能,相对于使用循环来处理嵌套结构,递归代码通常更简洁、易于理解和维护。
(2)可读性:
递归可以使代码更加可读和自解释,特别是对于涉及嵌套结构的问题,递归代码可以 更直观地表示问题的解决方案3。
(3)灵活性:
递归可以应对未知深度的数据结构,因为它不需要提前知道要处理的嵌套层级3。
(4)问题分解:
递归通过将问题划分为更小的子问题,使得复杂问题的解决变得更加可行。
-
递归的缺点:
(1)性能开销:
递归可能会导致性能问题,尤其是当递归层级很深时。每次递归调用都需要在内存中创建一个新的函数上下文,这可能会占用大量的内存和处理时间3。
(2)栈溢出:
如果递归层级过深,函数调用的堆栈可能会超出系统的限制,导致栈溢出错误。这通常可以通过限制递归层级或使用尾递归优化来避免3。
(3)难以调试:
由于递归涉及到函数的自我调用,调试递归函数可能会变得复杂和困难。错误的递归调用可能导致死循环或无限递归,从而使得调试变得更加困难3。
4.方法的定义中,是否必须要有返回值类型?如果确实不需要返回值,使用哪个关键字声明?
在Java中,方法的定义中不是必须要有返回值类型。 如果方法不需要返回任何数据,可以使用void关键字声明。
在Java中,方法可以分为有返回值和无返回值两种类型。如果方法不需要返回任何数据,即执行某些操作但不产生结果,可以使用void关键字声明。这种情况下,方法内部不能使用return返回数据。
5.方法的定义中,return是否必须?它有什么作用?
在方法的定义中,return不是必须的关键字,但在有返回值的方法中是必须的。
-
return语句的主要作用:
(1)返回值:
return语句用于将方法的执行结果返回给调用者。如果方法声明了返回类型,return语句必须返回一个与返回类型兼容的值。
(2)结束方法执行:
return语句可以提前结束方法的执行,即使方法体中还有未执行的代码。这有助于控制程序的流程,提高代码的可读性和可维护性。
(3)控制程序流程:
在循环或条件判断中,return语句可以用于提前结束循环或从多层嵌套结构中跳出,从而实现更精细的控制流程管理。
(4)错误处理
return语句还可以用于错误处理。在函数中遇到错误时,可以通过return语句返回一个特定的错误码或信息,以便调用者进行相应的处理
6.java中,参数的传递使用值传递还是引用传递?
(1)在Java中,参数的传递可以是值传递,也可以是引用传递。
(2) 基本数据类型作为参数时进行的是值传递,而对象引用类型作为参数时进行的是引用传递。
7.方法定义中,形式参数和实际参数有什么区别?用自己的话描述。
-
定义:
(1)形式参数:
在定义函数或方法时,函数名后面的括号中的参数称为形式参数。形式参数在函数调用时才会被实际参数所取代,它只是一个占位符,用于接收实际参数的值。
(2)实际参数:
在调用函数或方法时,传递给函数的参数称为实际参数。实际参数是真实传递给函数的值,可以是常量、变量、表达式或函数等。
-
作用范围和生命周期:
(1)形式参数:
形式参数只在函数或方法定义的作用域内有效,当函数调用完成后,形式参数会自动销毁。形式参数的作用域仅限于函数内部,函数外部无法访问。
(2)实际参数:
实际参数在函数调用时传递给函数,其作用范围为调用函数的过程中。实际参数在函数调用时被传递,并在函数内部被形式参数接收和使用。
-
内存分配:
(1)形式参数:
在函数调用时,形式参数会接收实际参数的值,但形式参数本身在函数定义时并不分配内存。形式参数的作用域仅限于函数内部,函数外部不识别形式参数。
(2)实际参数:
在函数调用时,实际参数需要分配内存地址,以便将值传递给形式参数。实际参数的作用域为调用函数的过程中。
-
传递方式:
(1)值传递:
当实际参数为不可变对象时,通常进行值传递。在这种情况下,改变形式参数的值不会影响实际参数的值。
(2)引用传递:
当实际参数为可变对象时,通常进行引用传递。在这种情况下,改变形式参数的值会影响实际参数的值。
8.方法定义时,使用实参还是形参?
在方法定义时,使用的是形参,而在方法调用时使用的是实参。
-
形参和实参的定义和作用
(1)形参:
在方法定义时使用的参数,用于接收外部传入的值。形参是方法签名的一部分,作为方法内部的局部变量,用于存储传入的实参值。形参只有在方法被调用时才会分配内存单元,并在方法调用结束后释放内存。
(2)实参:
在方法调用时传递给方法的实际值或对象的引用。实参用于传递数据给方法内部使用,可以是基本数据类型或对象引用。
-
形参和实参的类型和数量
(1)类型:
形参和实参都可以是基本数据类型(如int、double等)或对象引用。形参具有特定的数据类型,而实参则是实际的数据值或对象引用。
(2)数量:
调用方法时提供的实参数量必须与方法定义中的形参数量一致。如果形参数量不匹配,会导致编译错误。
-
形参和实参的传递方式:
(1)值传递:
当传递基本数据类型时,是将实际参数的值复制给形式参数。在这个过程中,实际参数的数值不会发生变化,形式参数的变化也不会影响实际参数。
(2)引用传递:
当传递对象引用时,传递的是引用地址,而不是值的复制。在这种情况下,形式参数和实际参数指向同一个对象,因此形式参数的改变会影响实际参数。
通过理解形参和实参的定义、类型、数量以及传递方式,可以更好地掌握Java中方法的定义和调用。
9.定义形参时,必须要写变量类型吗?
在编程语言中,定义形参时必须明确指定变量的类型。这是因为类型信息对于编译器来说非常重要,它帮助编译器进行类型检查,确保函数调用的正确性。
形参的定义规则
(1)必须指定类型:
每个形参都必须声明其数据类型。例如,int, double, String等。
(2)命名规则:
形参的命名应简洁明了,能够反映参数的作用或含义。通常使用小写字母开头,如果由多个单词组成,从第二个单词开始使用大写字母(驼峰命名法)。
(3)作用域:
形参的作用域仅限于定义它的方法内部,一旦方法执行完毕,形参的作用域也随之结束。
通过遵循这些规则,可以确保代码的可读性和维护性,同时避免编译错误。
10.实参类型是否必须和形参类型匹配?
在Java中,实参的类型必须和形参的类型兼容,并且在赋值过程中可以进行自动的类型转换(也称为装箱和拆箱)。如果实参类型与形参类型不匹配,编译器会报错。
形参和实参的类型匹配规则:
(1)基本数据类型:
实参的类型必须严格等同于形参的类型。
(2)对象类型:
实参类型可以是形参类型或其子类型。