Java经典算法+分析
程序员文章站
2024-03-15 16:33:00
...
1:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
- 分析:兔子对数的规律为数列1,1,2,3,5,8,13,21....,即每过3个月兔子的对手是前两个月之和,运用递归的思想即
math(x-1)+math(x-2)
。好程序如下:
public class Test01 {
public static void main(String[] args) {
int i = 0;
for(i=1;i<=20;i++){
System.out.println("第"+i+"月的兔子个数为:"+math(i)*2);
}
}
private static int math(int i) {
if(i==1||i==2){
return 1;
}
return math(i-1)+math(i-2);
}
}
2:判断101-200之间有多少个素数,并输出所有素数。
- 分析:如果该数能被2整除即不是素数反之即是素数,代码如下:
public class Test02 {
public static void main(String[] args) {
int count = 0;
int j = 2;
for (int i = 101; i < 201; i++) {
for(j=2;j<i;j++) {
if ((i % j) == 0) {
break;
}
}
if (j==i) {
count++;
System.out.println(i+"这个数为素数");
}
}
System.out.println("101-200之间一共"+count+"个素数");
}
}
3:打印出所有的 "水仙花数 ",所谓 "水仙花数 "是指一个三位数,其各位数字立方和等于该数本身。 例如:153是一个 "水仙花数,因为153=1的三次方+5的三次方+3的三次方。
- 分析:将各位数取出后进行
Math.pow(x,3)
并求和如果等于原始数即为水仙花数,代码如下:
public class Test3 {
public static void main(String[] args) {
for (int i = 100; i <= 999; i++) {
if (i == math(i)) {
System.out.println(i + "是一个水仙花数");
}
}
}
private static int math(int i) {
int g = i%10;
int s = i%100/10;
int b = i/100;
return (int) (Math.pow(b,3)+Math.pow(s,3)+Math.pow(g, 3));
}
}
4:将一个正整数分解质因数。例如:输入90,打印出90=233*5。
- 分析:如果该数能被一个小于它的数整除,那么利用递归将商传递下去,直到得到一个只能被该数本身整除的数停止递归。代码如下:
public class Test04 {
StringBuilder sb = new StringBuilder();
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入一个正整数:");
String n = scan.next();
System.out.print(n+"=");
math(Integer.valueOf(n));
}
private static void math(int n) {
for(int i=2;i<n;i++){
if (n%i==0) {
System.out.print(i+"*");
math(n/i);
}
}
System.out.println(n+"");
System.exit(0);// 不能少了这一句
}
}
5:利用条件运算符的嵌套来完成此题:学习成绩> =90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。
- 分析:条件运算符的格式
判断条件?条件成立的结果:条件不成立的结果
。代码如下:
public class Test05 {
public static void main(String[] args) {
Random random = new Random();
int n = random.nextInt(101);
String str = (n<60?"C":(n<90?"B":"A"));
System.out.println("该学生的成绩是:"+n+",评级为:"+str);
}
}
6:输入两个正整数m和n,求其最大公约数和最小公倍数。
- 分析:辗转相除法,又称欧几里得算法。两个整数的最大公约数是能够同时整除它们的最大的正整数。辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数的差的最大公约数。这里刚开始的时候使用一种比较笨的方式来求最小公倍数,作为一种思路也发给大家看看啊。代码如下:
public class Test06 {
public static void main(String[] args) {
Random random = new Random();
int a = random.nextInt(300);
int b = random.nextInt(300);
int gcd = countGCD(a,b);// 求最大公约数的方法
//int lcm = countLCM(11,10);// 求最大公倍数的方法
int lcm = a*b/gcd;// 两个数的乘积等于最大公约数与最小公倍数的乘积
System.out.println(a+","+b+" 的最大公约数为:"+gcd);
System.out.println(a+","+b+" 的最小公倍数为:"+lcm);
}
private static int countLCM(int a, int b) {
int t = a>b?a:b;
while(true){
if(t%a==0&&t%b==0){
return t;
}
t++;
}
}
private static int countGCD(int a, int b) {
while(true){
if((a=a%b)==0){
return b;
}
if((b=b%a)==0){
return a;
}
}
}
}
7:输入一行字符,分别统计出其\英文字母、汉字的个数。
- 分析:利用正则表达式来进行统计,
[\u4e00-\u9fa5]
代表匹配汉字的正则表达式。代码如下:
public class Test07 {
public static void main(String[] args) {
String m1 = "[a-zA-Z]";// 匹配字母的正则表达式
String m2 = "[\u4e00-\u9fa5]";// 匹配汉字的正则表达式
int e = 0;// 统计字母的个数
int h = 0;// 统计汉字的个数
Scanner scan = new Scanner(System.in);
System.out.println("请输入一串字符:");
char[] cArr = scan.nextLine().toCharArray();
String[] strArr = new String[cArr.length];
for (int i = 0; i < cArr.length; i++) {
strArr[i] = String.valueOf(cArr[i]);
}
for(String str:strArr){
if(str.matches(m1)){
e++;
}
if(str.matches(m2)){
h++;
}
}
System.out.println("输入字母的个数为:"+e);
System.out.println("输入汉字的个数为:"+h);
}
}
8:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加),几个数相加有键盘控制。
- 分析:我的思考是用户输入几个数相加,每次循环控制加数2出现的个数。网上的另外一种解法写的更加巧妙,循环内部通过自身不断的乘10加自身来完成每次计算时应出现的加数。具体代码如下:
public class Test08 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入几个数相加:");
int n = scan.nextInt();
int sum = 0;
for (int i = 0; i < n; i++) {
StringBuilder sb = new StringBuilder();
for(int j=0;j<=i;j++){
sb.append("2");
}
System.out.println(sb.toString());
sum+=Integer.parseInt(sb.toString());
}
System.out.println("和为:"+sum);
}
}
Other:
private static void other(int n) {
int sum=0;
int t=2;
if(n==0){
sum = 0;
}else{
sum = t;
}
for(int i=1;i<n;i++){
t = t*10+2;
sum+=t;
}
System.out.println("other和为:"+sum);
}
9:一个数如果恰好等于它的因子之和,这个数就称为 "完数 "。例如6=1+2+3.编程,找出1000以内的所有完数。
- 分析:将该数能够整除的数全部相加,如果等于该数本身即是完数。具体代码如下:
public class Test09 {
public static void main(String[] args) {
System.out.println("1000以内的所有完数包括:");
for(int i=1;i<=1000;i++){
int sum=0;
for(int j=1;j<i;j++){
if(i%j==0){
sum+=j;
}
}
if(sum==i){
System.out.print(i+" ");
}
}
}
}
10:一球从100米高度*落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高?
- 分析:除第一次落地以外其他每次落地都要经历上升和下落两段距离。具体代码如下:
public class Test10 {
public static void main(String[] args) {
double l = 100;
double sum = 100;
for(int i=1;i<2;i++){
sum+=l;
l = l/2.0;
}
System.out.println("第10次落地时经过了:"+sum+" 米");
System.out.println("第10次反弹 "+l+" 米");
}
}
11:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
- 分析:组成的三位数各位数都不相等。具体代码如下:
public class Test11 {
public static void main(String[] args) {
int n=0;
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
for (int k = 1; k <= 4; k++) {
if (i!=k&&j!=k&&i!=j) {
n++;
System.out.println(i*100+j*10+k);
}
}
}
}
System.out.println("一共组成了 "+n+" 个三位数");
}
}
12:一个整数,它加上100后是一个完全平方数,加上168又是一个完全平方数,请问该数是多少?
- 分析:这里需要用到一个方法Math.floor(double),该方法将返回一个无限接近该double值的一个整数。具体代码如下:
public class Test12 {
public static void main(String[] args) {
System.out.println("Math.floor():"+Math.floor(101.1));
long k=0;
for (k = 1; k < 100000; k++) {
if (Math.floor(Math.sqrt(k+100))==Math.sqrt(k+100)&&Math.floor(Math.sqrt(k+168))==Math.sqrt(k+168)) {
System.out.println(k);
}
}
}
}
13:输入某年某月某日,判断这一天是这一年的第几天?
- 分析:看了一下网上的解法,解的不是很巧妙,我这里给大家一个巧妙的解法利用case语句的穿透来实现。具体代码如下:
public class Test13 {
public static void main(String[] args) {
int day = 0;
int month = 0;
int year = 0;
int sum = 0;
System.out.println("请输入年,月,日:");
Scanner scan = new Scanner(System.in);
year = scan.nextInt();
month = scan.nextInt();
day = scan.nextInt();
switch(month){
case 12:
sum += 30;
case 11:
sum += 31;
case 10:
sum += 30;
case 9:
sum += 31;
case 8:
sum += 31;
case 7:
sum += 30;
case 6:
sum += 31;
case 5:
sum += 30;
case 4:
sum += 31;
case 3:
sum += 28;
case 2:
sum += 31;
case 1:
sum += day;
}
// 判断是否为闰年
if((year%400==0||(year%4==0&&year%100!=0)) && month>2){
sum++;
}
System.out.println("你输入的日期是"+year+"年的第 "+sum+" 天");
}
}
14:输入三个整数x,y,z,请把这三个数由小到大输出。
- 分析:注意比较顺序,x与y比,x与z比,最后y与z再比。具体代码如下:
public class Test14 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入三个整数:");
int x = scan.nextInt();
int y = scan.nextInt();
int z = scan.nextInt();
int t = 0;
if (x > y) {
t = x;
x = y;
y = t;
}
if (x > z) {
t = x;
x = z;
z = t;
}
if (y > z) {
t = y;
y = z;
z = t;
}
System.out.println("这三个数由小到大输出:" + x + " " + y + " " + z);
}
}
15:输出9*9口诀。
- 分析:这个太基础了吧,注意转义符的用法输出更美观。具体代码如下:
public class Test15 {
public static void main(String[] args) {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j+"*"+i+"="+(i*j)+"\t");
}
System.out.print("\n");
}
}
}
16:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下 的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。
- 分析:采取逆向思维,从第10天往前推,前一天的桃子数总是后一天桃子的(起始数+1)*2。具体代码如下:
public class Test16 {
public static void main(String[] args) {
int n = 1;
for(int i=9;i>=1;i--){
n=2*(n+1);
}
System.out.println("第一天一共摘了"+n+"个桃子");
}
}
网上利用递归思想来实现代码如下:
private static int total(int day) {
if(day==10){
return 1;
} else {
// 当天桃子数总是(后一天桃子数+1)*2
return (total(day+1)+1)*2;
}
}
17:题目:两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。
- 分析:采用穷举法,把所有组合都罗列出来,再按指定条件进行筛选,不知道大家还有没有更简便的方法。具体代码如下:
public class Test17 {
public static void main(String[] args) {
String[] A = new String[] { "a", "b", "c" };
String[] B = new String[] { "x", "y", "z" };
List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
String str = B[i] + B[j] + B[k];
if(str.indexOf("x")!=-1 && str.indexOf("y")!=-1 && str.indexOf("z")!=-1){
if (str.indexOf("x") != 0 && str.indexOf("x") != 2
&& str.indexOf("z") != 2) {
list.add(str);
System.out.println(str);
System.out.println(str.indexOf("x"));
}
}
}
}
}
for(String arr:list){
char[] cArr = arr.toCharArray();
for(int i=0;i<A.length;i++){
System.out.println(A[i] + "的对手为: " + cArr[i]);
}
System.out.println("-------------------------");
}
}
}
18:题目:发现文件夹内部的所有文件名以及文件夹名称(包括子文件夹内部的文件及文件夹)。
- 分析:采用递归算法。具体代码如下:
public class TestFile5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<File> list = findFiles("E:/test/1");
ArrayList<String> fileName = new ArrayList<>();
ArrayList<String> dirName = new ArrayList<>();
getName(list, fileName, dirName);
System.out.println("All files name: " + fileName);
System.out.println("All dirs name: " + dirName);
}
private static void getName(List<File> list, ArrayList<String> fileName, ArrayList<String> dirName) {
int n = list.size();
for(int i=0;i<n;i++) {
if(list.get(i).isFile()) {
fileName.add(list.get(i).getName());
} else {
getName(findFiles(list.get(i).getAbsolutePath()),fileName,dirName);
dirName.add(list.get(i).getName());
}
}
}
private static List<File> findFiles(String path) {
File fileDir = new File(path);
File[] fileList = fileDir.listFiles();
List<File> list = Arrays.asList(fileList);
return list;
}
}
上一篇: 1078 字符串压缩与解压 (20 分)
下一篇: Java实验2 类与对象