第一道:题目是写一个函数,输入int型,返回整数逆序后的字符串,要求必须使用递归,不能用全局变量,输入必须是一个参数,必须返回字符串。例如:将一个整数逆序后放如一数组中(要求递归实现)Ex:1234变为{4,3,2,1}。
当时拿到这道题目的,当初想把int型转换成string,然后再存近到数组中,然后使用递归的快排,呵呵!后来想了许久发现偏题加不可能,题目要求不能使用全局变量,即只能使用局部变量,即只有一个函数,但题目有要求用递归一下子难住了。。。。后来就网上看别人的算法实现了,我记得郝斌老师曾说过如果一个算法你想不出来就去学习别人的,别在这浪费时间,因为看别人的代码也是一种学习,掌握他们的算法思想更重要。
这里我解释一下核心算法的具体实现过程,期间有还是有些疑惑的我提出来,希望看到的网友能给予正解,就是我们知道对一个多位数取单个位数用到的无非是整除和取余,这个基本思想要知道,后面就简单了。核心算法:num%10+f(num/10) 这里首先要了解3个知识点,第一个就是因为倒序所以取余要放在前面,你要很清楚对10取余就是取最后一个位整数即个位上的数,第二你要知道任何数整除以10的商都是去除最末尾的数字剩下的数字,这个可以理解为小数点向左移一位然后去整。哈哈!有没有发现这完全就是小学的知识,第三就是递归思想,找到根源解决问题,就是把多位数每次除10后就相当于少了一位,然后再次带入函数中去末尾,去末尾剩下的数字,这样就会越来越少,即当num小于10的时候,就可以直接返回该数,当然题目要求是返回字符串类型,所以调用了String中的valueOf()方法来将整型转换成字符串类型。其实这里我疑惑的就是我感觉只有最后的一个数字被转换成String类型,其他仍然是int型,不知道我的理解对不对,感觉不对希望网友们可以指出。
废话不多说,附上别人的代码供大家一起学习:
public class Test1 {
public static void main(String[] args) {
System.out.println(f(1234));
}
public static String f(int a)
{
if(a>10)
return a%10+","+f(a/10);
else
return String.valueOf(a);
}
}
最后的输出是 4,3,2,1
第二道题目:编程输出一个目录下的所有目录以及文件名称,目录之间用tab。
这道题目个人感觉就是考你对文件那块的方法熟不熟悉,记住了很轻松。要是记不住怎么也写不出来,这道题目用到的主要是两个主要的方法:
1.listFile()能够获取当前文件下的所有文件和文件夹;
2.isDirectory()就是从所有文件和文件中过滤出所有文件,如果是目录就返回true,否则返回false。
package test;
import java.io.File;
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Test2().read("D:/test","");
}
public void read(String path,String tab){
//根据指定path生成了一个文件流,相当于程序和path路径文件的一个管道,即创建了一个File对象。
File file=new File(path);
//listFiles能够获取当前文件夹下的所有文件和文件夹,如果文件夹A下还有文件D,那么D也在childFiles里
File[] childFiles=file.listFiles();
//对数组里面的文件和文件夹进行遍历输出
for(int i=0;childFiles!=null&&i<childFiles.length;i++)
{
System.err.println(tab+childFiles[i].getName());//用getName获取文件的名字
//这里使用isDirctory()方法判断该文件是否为目录,是返回true,否则false
if(childFiles[i].isDirectory()){
read(childFiles[i].getPath(),tab+"\t");//返回该目录的相对路径
}
}
}
}
第三道题目就是下面代码输出顺序:
public class Test3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t=new Thread(){
public void run(){
test();
}
};
Thread t1=new Thread(){
public void run(){
v();
}
};
t1.start();
t.start();
f();
System.out.print("ping");
}
static void test(){
System.out.print("test");
}
static void v(){
System.out.print("hyj");
}
static void f(){
System.out.print("abc");
}
static{
System.out.print("11111");
}
}
//输出结果为11111hyjabcpingtest,后面hyj abc ping test执行顺序不确定,先后都有可能
我们必须知道:除了静态代码块(注意不包括静态方法)不管在main方法前面还是后面,总是首先执行!!这个一定要知道,然后后面t线程,t1线程,main线程执行顺序都是不确定的。
如果掌握了上面东西,我们接下来看看下面的代码块,猜猜输出顺序又如何?
class HelloA{
public HelloA(){
System.out.println("HelloA");
}
{System.out.println("I'm A class");}
static{System.out.println("static A");}
}
class HelloB extends HelloA{
public HelloB(){
System.out.println("HelloB");
}
{System.out.println("I'm B class");}
static {System.out.println("static B");}
}
public abstract class Test5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
new HelloB();
}
}
//首先主方法中是new了一个子类的对象,这时候要了解的是构造子类对象,必然会调用父类的构造函数,然后再调用自己的构造函数;
//先是跳进父类HelloA中代码中,上一题目的代码告诉我们若有静态代码块,就先执行静态代码块!!,这个时候很多人认为然后调用父类的构造函数,当然我也是这样认为
//但是我运行代码后就会发现,同样会跳到子类代码中先把子类的静态代码块执行了!!
//然后会执行父类中的非静态代码块,再执行父类的构造函数
//最后同样执行子类的非静态代码块,再执行子类的构造函数
//总结:1.静态优先执行,父类优先于子类执行,且静态代码块只执行一次;2.非静态代码块即动态代码块优先与构造函数;3.父类构造函数优先于子类构造函数;
所以最后的输出结果为:
static A
static B
I'm A class
HelloA
I'm B class
HelloB
我们可以记成这样:
父类--静态代码块
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数