Java编程初级练习题
前言
本文的目的旨在通过练习,提高逻辑思维能力,和算法优化能力。
11.排列问题 递归算法
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 分析:多重for循环在数字少时可以用,数字一多书写很麻烦,显然不是合适算法。递归算法本质上时间复杂度跟for一样,但是书写简捷,可以理解为有顺序的取出三个数,每次取数不放回;分为3次向栈中放数字,如果栈中没有这个数字就放入,有就不放。import java.util.Stack;
public class Main {
static int count=0;//类变量
static Stack<Integer> s = new Stack<Integer>();//类变量,可以直接在main里面用
public static void fun(int minl,int maxl,int curnum,int maxnum) {
if(curnum==maxnum) {
count++;
System.out.println(s);
return;//结束函数调用
}
for(int i = minl; i <= maxl; i++){
if(!s.contains(i)) {
s.push(i);
fun(minl, maxl, curnum+1, maxnum);
s.pop();
}
}
}
public static void main (String[] args){
fun(1, 4, 0, 3);
System.out.println(count);
}
}
12.奖金(等价于税收问题)
题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数?分析,每次会用到之前分段的总和,可以利用函数内调用函数方式避免重复;
import java.util.Scanner;
public class Main {
public static double premium(double profit){
double premium = 0;
if(profit>=0 && profit <= 100000){
premium = profit*0.1;
}else if(profit > 100000 && profit <= 200000){
premium = (profit - 100000) * 0.075 + premium(100000);
}else if(profit > 200000 && profit <= 400000){
premium = (profit - 200000) * 0.05 + premium(200000);
}else if(profit > 400000 && profit <= 600000){
premium = (profit - 400000) * 0.03 + premium(400000);
}else if(profit > 600000 && profit <= 1000000){
premium = (profit - 600000) * 0.015 + premium(600000);
}else{
premium = (profit - 1000000) * 0.01 + premium(1000000);
}
return premium;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
System.out.println("请输入利润数:");
double profit = in.nextDouble();
System.out.println("奖金为"+premium(profit));
in.close();
}
}
13.完全平方数
题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少? 分析:先构造完全平方数判断函数;再循环找数。import java.util.Scanner;
public class Main {
public static boolean perfectsqure(int num){
boolean flag=false;
if(num==0) {
flag=true;
}
else {
for(int i=1;i<Math.sqrt(num)+1;i++) {
if((double)num/i==i)
flag=true;
}
}
return flag;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int x=0;
while(true) {
if(perfectsqure(x+100) && perfectsqure(x+268)) {
System.out.print("这个数是:"+x);
break;
}
x++;
}
in.close();
}
}
14、日期 函数内调用函数
题目:输入某年某月某日,判断这一天是这一年的第几天?
分析:题目有两个注意点一是闰年平年判断,二是字符串的拆解,此处计算天数用到了12题的技巧。
import java.util.Scanner;
public class Main {
public static void day(String s){
int day=0;
String[] a = s.split("-");
if(isleap(Integer.parseInt(a[0]))) {
int mm=Integer.parseInt(a[1]);
day=sumday(mm-1)+Integer.parseInt(a[2]);
}
else {
int mm=Integer.parseInt(a[1]);
if(mm>2)
day=sumday(mm-1)+Integer.parseInt(a[2])-1;
else
day=sumday(mm-1)+Integer.parseInt(a[2]);
}
System.out.printf("第%s年的第%d天\n",a[0],day);
}
public static int sumday(int m) {
int sum=0;
switch (m){
case 1: sum=31; break;
case 2: sum=sumday(1)+29; break;
case 3: sum=sumday(2)+31; break;
case 4: sum=sumday(3)+30; break;
case 5: sum=sumday(4)+31; break;
case 6: sum=sumday(5)+30; break;
case 7: sum=sumday(6)+31; break;
case 8: sum=sumday(7)+31; break;
case 9: sum=sumday(8)+30; break;
case 10: sum=sumday(9)+31; break;
case 11: sum=sumday(10)+30; break;
default: break;
}
return sum;
}
public static boolean isleap(int y) {
if(y%100!=0 && y%4==0 || y%400==0) {
return true;
}else
{
return false;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("请输入日期,格式为yyyy-mm-dd:");
Scanner in = new Scanner(System.in);
String s = in.nextLine();
day(s);
in.close();
}
}
15、比大小 冒泡排序
题目:输入三个整数x,y,z,请把这三个数由小到大输出
分析:简单可以直接用if,为了通用比较三个以上的,本处利用冒泡排序
public class Main {
public static void sort(int...a ){
for(int i=1;i<a.length;i++)
for(int j=0;j<a.length-i;j++) {
int temp=0;
if(a[j]>a[j+1]) {
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
for(int k: a) {
System.out.print(k+" ");
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
sort(3,6,7,8,1,2,0);
}
}
16、乘法口诀表
题目:输出9*9口诀。
public class Main {
public static void main(String[] args) {
for(int i=1;i<10;i++) {
for(int j=1;j<=i;j++) {
System.out.printf("%d*%d=%d ",j,i,i*j);
}
System.out.println();
}
}
}
17、猴子吃桃 递归算法
题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少
分析:可以反过来看,第1天早上采了a个,第2天吃2(a+1),即f(n)=2(f(n-1)+1),已知第一天采了一个,第10天采了多少个,可采用递归算法
public class Main {
public static int sum(int days){
if(days == 1){
return 1;
}else if(days > 1){
return (sum(days-1) + 1) * 2;
}
return 0;
}
public static void main(String[] args) {
System.out.print(sum(10));
}
}
18、抽签比赛
题目:两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。
分析;列出所有可能组合,将不符合的排除
public class Main{
public static void main(String[] args) {
for(char i ='x';i<='z';i++){
for(char j ='x';j<='z';j++){
if(i!=j)
for(char k = 'x';k<='z';k++){
if(i!=k&&j!=k)
if(i!='x'&&k!='x'&&k!='z') {
System.out.println("a与" + i + "比赛");
System.out.println("b与" + j + "比赛");
System.out.println("c与" + k + "比赛");
}
}
}
}
}
}
19、打印菱形
题目:打印出如下图案(菱形)
分析:可以看做看做是由空格,*,组成,下一半开头缩进一个,每次少画一颗星,上一半刚好相反
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println("请输入项数:");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
//上一半
for(int i=1;i<n;i++) {//倒过来画一遍
for(int k=0;k<n-i;k++) {//表示缩进格数
System.out.print(" ");
}
for(int j=n-i;j<n;j++) {//画的个数每次增加
System.out.print("* ");
}
System.out.println();//每层画完换行
}
//下一半
for(int i=n;i>0;i--) {
for(int k=0;k<n-i;k++) {//表示缩进格数
System.out.print(" ");
}
for(int j=n-i;j<n;j++) {//画的个数每次减少
System.out.print("* ");
}
System.out.println();//每层画完换行
}
in.close();
}
}
20、分数列求和 递归算法
题目:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13…求出这个数列的前20项之和。
分析:分子分母都是斐波那契数列的一部分,斐波那契数列可以用递归算法给出
public class Main {
public static int fib(int n) {
if(n==1 || n==2)
return 1;
else
return fib(n-1)+fib(n-2);
}
public static void main(String[] args) {
System.out.println("请输入项数:");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
double result=0;
for(int i=0;i<n;i++) {
result+=(double)fib(i+3)/fib(i+2);
}
System.out.printf("前%d项和为%.2f \n",n,result);
in.close();
}
}