练习题
1.计算输入数的阶乘
循环和递归
(1)递归
public static int func1(int n){
int res = 1;
if(n==1){
return 1;
}
for (int i = 1; i <= n; i++) {
res*=i;
}
return res;
}
(2)递归
递归的条件:
- 可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式。(自身调用自身)
- 存在一种能够简单情景,可以使递归在简单情境加退出。(结束递归)
递归三要素:
- 一定有一种可以退出程序的情况;
- 总是在尝试将一个问题化简到更小的规模;
- 父问题与子问题不能有重叠的部分。
public static void main(String[] args) {
//计算输入数据的阶乘值
System.out.println("10! = "+func(10));
}
public static int func(int num){
if(num==1){
return 1;
}else{
return num*func(num-1);//递归的主要步骤,自身调用自身
}
}
2.互换两个数的值(不允许使用中间变量)
public static void func(int num1,int num2){
num1 = num1+num2;//num1 = 1,num2 = 2
num2 = num1-num2;//num1 = 3,num2 = 1
num1 = num1-num2;//num1 = 2,num2 = 1
System.out.println("num1 = "+num1);
System.out.println("num2 = "+num2);
}
3.输出三个数中的最大值和最小值
结题思路:1、前两个数值进行比较,获取较大的数。2、同第一步,在一种获取较大的,与第三个进行比较,获取最大值。
//自定义方法
int[] arr = new int[3];
Scanner sc = new Scanner(System.in);
for(int i = 0;i<arr.length;i++){
System.out.println("请输入第"+(i+1)+"个整数:");
int num = sc.nextInt();
arr[i] = num;
}
int num = arr[0]>arr[1]?arr[0]:arr[1];
int max = num>arr[2]?num:arr[2];
System.out.println("最大值为:"+max);
//Java内部方法
int[] arr = new int[3];
Scanner sc = new Scanner(System.in);
for(int i = 0;i<arr.length;i++){
System.out.println("请输入第"+(i+1)+"个整数:");
int num = sc.nextInt();
arr[i] = num;
}
int num = Math.max(arr[0],arr[1]);
int max = Math.max(num,arr[2]);
System.out.println("最大值为:"+max);
//使用三目运算符
int k1 = 1,k2 = 3;
int num = k1>k2?++k1:k2++;//由于表达式1为true,所以执行表达式2,但是不执行表达式3
System.out.println(num+":"+k1+"=="+k2);
4.输出1-100的奇数(每行输出6个)
public static void main(String[] args){
int count = 0;
for(int i = 1;i<=100;i++){
if(i%2!=0){
System.out.print(i+"\t");
if(++count%6==0){
System.out.println();
}
}
}
}
5.1-100求和(三种循环写法)
在这里插入代码片
6.1-100奇数求和
int res = 0;
for(int i = 1;i<100;i=i+2){
res+=i;
}
int num = 0;
for(int k = 1;k<=100;k++){
if(k%==0)continue;
num+=k;
}
7.输出1-100可以被3整除的数,每行输出6个
for(int i = 3;i<100;i=i+3){
System.out.println(i);
}
int count = 0;
for(int k = 1;k<=100;k++){
if(k%3==0){
System.out.print(k+"\t");
if(++count%6==0)
System.out.println();
}
}
8.求100以内所有能被3整除但不能被5整除的个数,每行输出6个
for(int i = 3;i<100;i=i+3){
System.out.println(i);
}
int count = 0;
for(int k = 1;k<=100;k++){
if(k%3==0||k%5!=0){
System.out.print(k+"\t");
if(++count%6==0)
System.out.println();
}
}
9.打印出所有的水仙花数
水仙花:值一个三位数,他的每个位上的数字的3次幂之和等于它本身。
int count = 0;
for(int i = 100;i<1000;i++){
int k1 = i%10;//个位数
int k2 = i/100;//百位数
int k3 = i/10%10;//十位数
if(i==(k1*k1*k1+k2*k2*k2+k3*k3*k3)){
//Math.pow(k1,3)
System.out.print(i+"\t");//测试用例153
if(++count%3==0)
System.out.println();
}
}
10.判断一个数是否是质数
质数:指大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
public static boolean suShu(int i){
boolean suShu = true;//判断i是否为质数
for(int k = 2;k<i/2;k++){
suShu = false;
break;
}
return suShu;
}
11.编程求出自然数101-205中的所有质数
public static void main(String[] args){
int count = 0;
for(int i = 101;i<=205;i++){
//判断i是否为质数
boolean b = suShu(i);
if(b){
System.out.print(i+"\t");
if(++count%6==0)//6个银行进行输出
System.out.println();
}
}
}
public static boolean suShu(int i){
boolean suShu = true;//判断i是否为质数
for(int k = 2;k<i/2;k++){
suShu = false;
break;
}
return suShu;
}
12.输入两个整数m和n,求其最大公约数和最小公倍数
最大公约数:指两个或者多个整数共有约数中最大的一个。
最小公倍数
public static void main(String[] args) {
int m, n;// 声明变量
Scanner sc = new Scanner(System.in);
System.out.println("输入整数1:");
while (true) {
// 无法预知用户需要输入多少次才能保证数据的正确有效
m = sc.nextInt();
if (m < 2)
System.out.println("输入的数据不合法,请重新输入");
else
break;
}
System.out.println("输入整数2:");
while (true) {
n = sc.nextInt();
if (n < 2)
System.out.println("输入的数据不合法,请重新输入");
else
break;
}
//需要对用户输入的数据进行合法性判断,以保证应用在执行的过程中不会出现特殊情况,来提高代码的健壮性
int gys = gongYueShu(m, n);
if (gys > 1)
System.out.println(m + "和" + n + "的最大公約數為:" + gys);
else
System.out.println(m + "和" + n + "互爲質數");
int gbs = gongbeishu(m,n);
System.out.println("公倍数为:"+gbs);
}
// 获取num1和num2两个整数的最大公约数,如果返回1則表示互为质数
//公约数
public static int gongYueShu(int num1, int num2) {
int res = 1;
int end = Math.min(num1, num2);
for (int i = end; i > 1; i--) {
// 实际上可以继续优化,来减少循环次数
if (num1 % i == 0 && num2 % i == 0) {
res = i;
break; // 如果获取到第一个约数,则没必要继续计算,得到的就是最大公约数
}
}
return res;
}
//公倍数
public static int gongbeishu(int num1, int num2){
int res = 1;
int end = Math.min(num1, num2);
for (int i = end; i > 1; i++) {
// 實際上最小值仍舊可以優化,以減少循環次數
if (i % num1 == 0 && i % num2 == 0) {
res = i;
break; // 如果獲取到第一個約數,則沒有必要繼續計算,這就是最大公約數
}
}
return res;
}
13.1000~50000之间有多少整数,其各位的数字之和为5,分别是那些数,并统计满足条件的整数由多少个
public static void main(String[] args) {
//1000~50000之间有多少整数,其各位的数字之和为5,分别是那些数,并统计满足条件的整数由多少个
for (int i = 100; i < 50000; i++) {
//如果是3位数
if (i >= 100 && i < 1000) {
int k1 = i % 10;//个位数
int k2 = i / 100;//百位数
int k3 = i / 10 % 10;//十位数
if (k1 + k2 + k3 == 5) {
System.out.println(i);
}
} else
//如果是4位数
if (i >= 1000 && i < 10000) {
int k1 = i % 10;//个位数
int k2 = i / 1000;//千位数
int k3 = i / 10 % 10;//十位数
int k4 = i / 100 % 10;//百位数
if (k1 + k2 + k3 + k4 == 5) {
System.out.println(i);
}
} else
//如果是5位数
if (i >= 10000) {
int k1 = i % 10;//个位数
int k2 = i / 10000;//千位数
int k3 = i / 10 % 10;//十位数
int k4 = i / 100 % 10;//百位数
int k5 = i / 1000 % 10;//千位数
if (k1 + k2 + k3 + k4 + k5 == 5) {
System.out.println(i);
}
}
}
}
14.鸡兔同笼共80个头,208只脚,鸡和兔各有几只
for (int i = 0; i <= 80; i++) {
int k = 80-i;
if(i*2+k*4==208)
System.out.println("其中有"+i+"只鸡,"+k+"只兔子");
}
15.鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何说明的问题是合理的评估循环次数
for (int i = 0; i <= 20; i++) {
//公鸡数
for (int j = 0; j <= 300; j+=3) {
//小鸡数
int k = 100-i-j;//母鸡数
if(k<0)
continue;
if(i*5+j/3+k*3==100)
System.out.println("公鸡:"+i+",母鸡:"+k+",小鸡:"+j);
}
}
16.声明员工类Employee,包含属性:编号、姓名、年龄、薪资,声明Test01测试类,并在main方法中,创建2个员工对象,并为属性赋值,同时打印两个员工的信息。
packege com.sxn.test1;//包名称就是一个命名空间,主要作用就是避免命名冲突,一般要求定义包名,因为默认包中的类只能同包访问,其他包无法访问。
//抽象数据类型
public class Emolpyee{
//一个文件中可以定义无数个类,但是只能有一个公共类,而且类名必须和文件名称一致。
//封装:将相关的数据和相关的操作定义在一个类中,对外提供访问接口,隐藏实现细节
//四个范围限定词:public导出可见、protected同包或子类中可见、默认package同包可见、private当前类内可见(稀有属性,公有的get/set方法,根据是否允许修改决定提供对应的方法)
private Long id;//身份证号
private String name;//姓名
//两种声明属性类型的方法,一般建议采用包装类,因为包装类的属性可以判断是否进行了赋值操作
//new一个对象,则属性有默认值:(1)数值型一般默认为0;(2)boolean默认false;(3)char类型默认为'\u0000',使用简单类型定义属性,则无法区分默认值是否进行了赋值操作。但是使用包装类就可以进行区分,因为复杂类型的属性默认值为null;
private int age;//年龄
private double salary;//薪资
//根据是否允许修改或者读取提供对应的get/set方法。针对复杂类型的默认命名规则为setXxx或者getXxx,如果是boolean类型则读取属性数据的默认方法为isXxx
public void setId(Long id){
this.id = id;//如果局部变量名称冲突,方法中的id是局部变量,则属性前需要加 this. 来区分变量
public Long getId(){
return this.id;
}
}
}
//测试定义类
package com.sxn.test1;
public class Test1{
public static void main(String[] args){
//创建对象,new运算符
Employee e = new Employee();//定义变量,这里会自动调用类中的无参构造器
e1.setId(1L);//L用于表示长整型
e1.setName("张三");//“”表示字符串类型
e1.setAge(23);
e1.setSalary(10000.);
System.outprintln(e1);//使用print进行打印输出时,实际上是默认调用Employee类中的toString方法,将对象转换为字符串进行输出。
}
}
17.声明公民类Citizen,包含属性:姓名,生日,身份证号,其中姓名是String类型,生日是MyDate类型,身份证号也是String类型,声明Test03测试类,在main方法中创建你们家庭成员的几个对象,并打印信息。
package com.sxn.test2//包名称
public class MyDate{
//默认继承于java.lang.Object类,不需要import语句导入。类名称的命名规则为首字母大写,大写字母分词
//成员属性(字段)。命名规则为小写字母开头,大写字母分词
int year;//范围限定词为默认package,知识同包可见
int month;
int date;
public void setYear(int year){
//方法名称的命名规则为小写字母开头,大写字母分词
}
public String toString(){
return year+"年"+month+"月"+date+"日";
}
}
//测试类
package com.sxn.test03;
import com.sxn.test02.MyDate;//导入其他包中的类,如果同包或者java.lang包则不需要导入语句
public class Citizen{
protected String name;//同包或者子类中可见
public MyDate birth;
private String carId;
public string getCardId(){
return carId;
}
public void setCardId(string carId){
this.cardId = cardId;
}
}
//测试类
public class Test3{
public static void main(String[] args){
Citizen c = new Citizen();
c.name = "张三";
MyDate dd = new MyDate();
//不能再直接使用dd.year设置年份,因为不同包,默认范围限定词只能同包可见,所以需要在MyDate中添加public的get/set方法
dd.setYear(2020);
dd.setMonth(1);
dd.setDate(27);
c.birth = dd;
// c.cardId = "12345";报错原因是private属性只能在Citizen类中直接访问,类外只能通过get/set方法访问
c.setCardId("12345");
System.out.println("家庭成员"+c.name+",生日为"+c.birth+",身份证号码"+c.getCardId());
}
}
18.方法定义练习:声明一个日期类MyDate,包含属性:年、月、日,并在MyDate类中声明几个方法:1.boolean isLeapYear():判断当前日期是闰年吗?2.void set(int y,int m,int d):修改年、月、日为新日期。3.void plus(int years,int months,int days):加上years年,months月、days后的日期并在测试类Test04的main方法中创建对象,并调试测试。
public class MyDate{
int year;
int month;
int date;
//判断当前是否是闰年
private boolean isLeapYear(){
return year%4==0 && year%100!=0 || 400==0;
}
//修改年、月、日为新日期
void set(int year,int month,int date){
this.year = year;
this.month = month;
this.date = date;
}
public void plus(int years,int months,int dates) {
this.year += years;
this.month += months;
this.date += dates;
while (this.month > 12) {
this.month -= 12;
this.year++;
}
while (true) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10) {
if (date > 31) {
date -= 31;
month++;
} else
break;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
if (date > 30) {
date -= 30;
month++;
} else
break;
} else if (month == 2) {
if (isLeapYear()) {
if (date > 29) {
date -= 29;
month++;
} else
break;
} else {
if (date > 28) {
date -= 28;
month++;
} else
break;
}
} else if (month == 12) {
if (date > 31) {
date -= 31;
month = 1;
year++;
} else
break;
}
}
}
@Override
public String toString(){
return "Test:"+year+"年"+month+"月"+date+"日";
}
public int getYear(){
return year;
}
public void setYear(int year){
this.year = year;
}
public int getMonth(int month){
return month;
}
public void setMonth(int month){
this.month = month;
}
public int getDate(){
return date;
}
public void setDate(int date){
this.date = date;
}
}
19. 声明一个三角形类Triangle,包含属性a、b、c,表示三条边,包含几个方法:
(1)boolean isRight isRightTriangle():判断是否是一个直角三角形。
(2)boolean isIsoscelesTriangle():判断是否是一个等腰三角形。
(3)boolean isEquilateralTriangle():判断是否是一个等边三角形。
(4)double getArea():根据三条边,用海伦公式求面积。
(5)double get Length():求周长。
public class Triangle{
private double a,b,c;
//判断是否是一个直角三角形
boolean isRightTriangle(){
if(a>0 && b>0 && c>0){
if(a+b>c && a+c>b && b+c>a){
if(a*a+b*b==c*c||a*a+c*c==b*b||b*b+c*c==a*a){
return true;
}
}
}
return false;
}
//判断是否是一个等腰三角形
public boolean isIsoscelesTriangle(){
if(a>0 && b>0 && c>0){
if(a+b>c && a+c>b&&b+c>a){
if(b==c||a==b||a==c){
return true;
}
}
}
return false;
}
//判断是否是一个等边三角形
public boolean isEquilateralTriangle(){
if(a>0 && b>0 && c>0){
if(a+b>c && a+c>b && b+c>a){
if(a==b && b==c){
return true;
}
}
}
return false;
}
//根据三条边用海伦公式求面积
public double getArea(){
if(a>0 && b>0 c>0){
if(a+b>c && a+c>b && b+c>a){
double p = (a+b+c)/2;
return Math.sqrt(p*(p-a)*(p-b)*(p-c));
}
}
return -1;
}
//求周长
double getLength(){
if(a>0 && b>0 && c>0){
if(a+b>c && a+c>b && b+c>a){
return a+b+c;
}
}
return -1;
}
public double getA(){
reutrn a;
}
public void setA(double a){
this.a = a;
}
public double getB(){
reutrn b;
}
public void setB(double b){
this.b = b;
}
public double getC(){
reutrn c;
}
public void setC(double c){
this.c = c;
}
}
//测试程序
public class Test{
public static void main(String[] args){
Triangle t = new Triangle();
t.setA(3);t.setB(4);t.setC(5);//小类型转大类型自动转
if(t.isRightTriangle()){
System.out.println("直角三角形");
}
System.out.println("面积为:"+t.getArea());
}
}
20. 声明一个数组管理工具类MyArrays,包含如下方法:
(1)void sort(int [] arr):可以为任意一维数组arr实现从小到大排序;
(2)int indexOf(int[] arr,int value):可以在任意一维整型数组arr中查找value值得下标。如果不存在则返回-1;
(3)int[] cpoy(int[] arr,int len):可以实现从任意一维数组arr中复制一个新数组返回,新数组的长度为len,从arr[0]开始复制;
public class MyArrays{
private MyArrays(){
}
//冒泡排序
public static void sort(int[] arr){
for(int i = 1;i<arr.length;i++){
for(int k = 0;k<arr.length-i;k++){
if(arr[k]>arr[k+1]){
int temp = arr[k+1];
arr[k+1] = arr[k];
arr[k] = temp;
}
}
}
}
//可以在任意一维整型数组arr中查找value值得下标,如果不存在返回-1
public static int indexOf(int[] arr,int value){
sort(arr);
return binarySearch(arr,value,0,arr.length-1);
}
private static int binarySearch(int[] arr,int target,int begin,int end){
if(begin > end)
return -1;
int mid = (begin + end) / 2;
if(arr[mid] < target){
//target大于中间值对后半段进行递归查询,end不变
begin = mid + 1;
}else if(arr[mid]>target){
//target小于中间值对前半段进行递归查询,begin不变
end = mid-1;
}else
return mid;
return binarySearch(arr,target,begin,end);//遍历寻找target
}
//可以实现从任意一维数组arr中复制一个新数组返回,新数组的长度为len,从arr[0]开始复制
public static int[] copy(int[] arr,int len){
int[] res = new int[len];
int newLen = Math.min(arr.length,len);
//方法一
// for(int i = 0;i<Math.min(arr.length,len);i++){
// res[i] = arr[i];
// }
// return res;
//方法二
System.arraycopy(arr,0,res,0,newLen);//调用System.arraycopy()方法对数组进行赋值
return res;
}
}
21. date的基本方法和数组的灵活使用,声明一个常识工具类DateCommonsTools,包含如下方法:
(1)String getWeekName(int week):根据星期值,返回对应的英语单词
(2)String getMonthName(int month):根据月份值,返回对应的英语单词
(3)int getTotalDaysMonth(int year,int month):返回某年某月的总天数
(4)int getTotalDaysYear(int year):获取某年的总天数
(5)boolean isLeapYear(int year):判断某年是否是闰年
根据星期值返回对应的单词
//根据星期值,返回对应的英文单词
public static String getWeekName(int week){
String[] arr = new String[]{
"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
if(week<0 || week>6)
return "";
return arr[week];
}
根据月份返回对应的单词
//根据月份值,返回对应的英文单词
public static String getMonthName(int month){
String[] arr = new String[]{
"January","February","March","April","May","June","July","","",""};
if(month<0||month>11)
return "";
return arr[month];
}
获取某年某月的总天数
//返回某年某月的总天数
public static int getTotalDaysOfMonth(int year,int month){
int res = 0;//用来记录返回的天数
switch(month){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
res = 31;
break;
case 4:
case 6:
case 9:
case 11:
res = 30;
break;
case 2:
if(isLeapYear(year))
res = 29;
else
res = 28;
default:
res = 0;
break;
}
return res;
}
获取年份的总天数
//获取某年的总天数
public static int getTotalDaysOfYear(int year){
if(isLeapYear(year))//判断是否是闰年
return 366;
else
return 365;
}
闰年的判断方法
//判断某年是否是闰年
private static boolean ifLeapYear(int year){
return year%4==0 && year%100!=0 || year%400==0;
//不能被4和100整活,或者不能被400整除的年份
}
测试类
public static void main(String[] args){
Date now = new Date(2021-1900,11-1,21);
int week = now.getDay();//获取星期几
System.out.println(getWeekName(week));
//格式化输出:yyyy-MM-dd HH:mm:ss 年-月-日 小时-分钟-秒
DateFormat df - new SimpleDateFormat("E");
System.out.println(df.format(now));//周日
//使用的是中文版的win,所以默认别国为中国
Locale loc = new Locale("en","us");//用于封装国别和语言信息
df = new SimpleDateFormat("E",loc);
System.out.println(df.format(now));//指定国别的格式Sun
System.out.println(now.getMonth());//获取月份值,月份值差1
System.out.println(getMonthName(now.getMonth()));
df = new SimpleDateFormat("M",loc);
System.out.println("月份:"+df.format(now));
df = new SimpleDateFormat("MMMM",loc);
System.out.println(df.format(now));
System.out.println(now.getYear()+1900);//获取年份,相差1900
}
22. 在一个长度为n的数组nums里的所有数字都在0 ~ n-1的范围内,数组中某些数字是重复的但不知道有几个数字重复了,也不知道每个数字重复了几次,请找出数组中任意一个重复的数字
23. 在一个长度为n+1的数组里的所有数字都在1~n范围内,所以数组中至少有一个数字是重复的。找出任意一个重复的数字,但不能修改输入的数组。
24.实现一个游戏中的发牌算法
public static void main(String[] args) {
String[] arr = new String[]{
"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
String[] res = new String[arr.length];
Random r = new Random();
for (int i = 0; i < arr.length; i++) {
while(true){
int pos = r.nextInt(arr.length);
if (arr[pos] != null){
//判断原数组位置是否为空
//将原数组随机位置的元素取出赋值给新数组
String str = arr[pos];
res[i] = str;
arr[pos] = null;//原数组赋值后将其置空,防止之后会重新取到该值
break;
}
}
}
for (String tmp:res) {
System.out.print(tmp+"\t");
//2 5 4 7 Q J 8 9 10 6 K 3 A
}
System.out.println();
for (String tmp:arr) {
System.out.print(tmp+"\t");
//null null null null null null null null null null null null null
}
}
25.判断一个整数是不是2的阶次方
public static void main(String[] args) {
int num = 8;
int count = num;
boolean res = true;
if (num>=2){
while(true){
if (count%2 != 0){
res = false;
break;
}
count/=2;
if (count ==1){
break;
}
}
}else{
res = false;
}
if (res)
System.out.println(num+"是2的阶次方");
else
System.out.println(num+"不是2的阶次方");
}