首页 > 技术文章 > 面试2 --- 递归算法

spstart 2019-09-06 14:12 原文

 1 例:        
 2     //求6的阶乘
 3     public class DiGeiDome {
 4         public static void main(String[] args) {
 5             int sum = getSum(6);
 6             System.out.println(sum);
 7         }
 8         
 9         public static int getSum(int n){//n=3
10             if (n==1) {
11                 return 1;
12             }else{
13                 return n*getSum(n-1);//3*getSum(2);getSum(2)=2*getSum(1)
14             }
15         }
16     }
17  

java中常见的递归使用场景

  1. 子问题须与原始问题为同样的事,且更为简单;
  2. 不能无限制调用本身,须有个出口,化简为非递归状态处理;
  3. 递归的次数不能太多,否则容易造成栈内存溢出(java.lang.StackOverflowError);
  4. 构造方法不能递归调用。

二、计算任意正整数的阶乘

由于受到intlong取值范围的限制,将数据转换成BigInteger包装类。但是受到电脑内存的限制,只能计算5000以内的正整数阶乘。

 1 import java.math.BigInteger;
 2 import java.util.Scanner;
 3 
 4 public class Recursion_Demo1 {
 5 
 6     public static void main(String[] args) {
 7         Scanner sc = new Scanner(System.in);
 8         System.out.println("求阶乘:");
 9         System.out.println(getFactorial(sc.nextInt()));
10     }
11     
12     public static BigInteger getFactorial(int num) {
13         if(num == 1) {
14             return BigInteger.ONE;
15         }
16         return BigInteger.valueOf(num).multiply(getFactorial(num - 1));
17     }
18 }

 

三、计算文件夹大小

由于File类下length()(返回值类型为long型)方法只能统计文件的大小,没有方法直接统计文件夹的大小,需要使用递归的方法遍历到所有的文件,并累加,最终计算出文件夹大小。

 1 import java.io.File;
 2 import java.util.Scanner;
 3 public class Recursion_Demo2 {
 4     public static void main(String[] args) {
 5         File dir = getDir();
 6         System.out.println(getFileLength(dir));
 7         System.out.println("统计完成!");
 8     }
 9     
10     public static File getDir() {
11         //1,创建键盘录入对象
12         Scanner sc = new Scanner(System.in);
13         System.out.println("请输入一个文件夹路径:");
14         //2,定义一个无限循环
15         while(true) {
16             //3,将键盘录入的结果存储并封装成File对象
17             String line = sc.nextLine();
18             File dir = new File(line);
19             //4,对File对象判断
20             if(!dir.exists()) {
21                 System.out.println("您录入的文件夹路径不存在,请重新录入:");
22             }else if(dir.isFile()) {
23                 System.out.println("您录入的是文件路径,请重新录入:");
24             }else {
25                 //5,将文件夹路径对象返回
26                 return dir;
27             }
28         }        
29     }
30     public static long getFileLength(File dir) {
31         //1,定义一个求和变量
32         long len = 0;
33         //2,获取该文件夹下所有的文件和文件夹listFiles();
34         File[] subFiles = dir.listFiles();
35         //3,遍历数组
36         if(subFiles != null) {
37             for (File subFile : subFiles) {
38                 //4,判断是文件就计算大小并累加
39                 if(subFile.isFile()) {
40                     len = len + subFile.length();
41                     //5,判断是文件夹,递归调用
42                 }else {
43                     len = len + getFileLength(subFile);
44                 }
45             }
46         }
47         return len;
48     }
49 }
View Code

四、删除指定目录

File类目录下boolean delete()方法:删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能删除。

因此只能通过遍历目录下所有的文件,并删除。

 1 import java.io.File;
 2 import java.util.Scanner;
 3 public class Recursion_Demo3 {
 4     public static void main(String[] args) {
 5         File dir = getDir();
 6         deleteFile(dir);
 7         System.out.println("删除成功!");
 8     }
 9     public static void deleteFile(File dir) {    
10         //1,获取该文件夹下的所有的文件和文件夹
11         File[] subFiles = dir.listFiles();        
12         //2,遍历数组
13         if(subFiles != null) {
14             for (File subFile : subFiles) {
15                 //3,判断是文件直接删除
16                 if(subFile.isFile()) {
17                     subFile.delete();
18                     //4,如果是文件夹,递归调用
19                 }else {
20                     deleteFile(subFile);
21                 }
22             }
23         }
24         //5,循环结束后,把空文件夹删掉
25         dir.delete();
26     }
27     public static File getDir() {
28         //1,创建键盘录入对象
29         Scanner sc = new Scanner(System.in);
30         System.out.println("请输入一个文件夹路径:");
31         //2,定义一个无限循环
32         while(true) {
33             //3,将键盘录入的结果存储并封装成File对象
34             String line = sc.nextLine();
35             File dir = new File(line);
36             //4,对File对象判断
37             if(!dir.exists()) {
38                 System.out.println("您录入的文件夹路径不存在,请重新录入:");
39             }else if(dir.isFile()) {
40                 System.out.println("您录入的是文件路径,请重新录入:");
41             }else {
42                 //5,将文件夹路径对象返回
43                 return dir;
44             }
45         }
46     }
47 }
View Code

 

五、拷贝文件夹

使用BufferedInputStreamBufferedOutputStream高效的拷贝文件夹。

 1 import java.io.BufferedInputStream;
 2 import java.io.BufferedOutputStream;
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.io.FileOutputStream;
 6 import java.io.IOException;
 7 import java.util.Scanner;
 8 public class Recursion_Demo4 {
 9     public static void main(String[] args) throws IOException {
10         System.out.println("请录入源文件夹:");
11         File src = getDir();
12         System.out.println("请录入目标文件夹:");
13         File target = getDir();
14         if(src.equals(target)) {
15             System.out.println("无法拷贝");
16         }else {
17             copy(src,target);
18             System.out.println("拷贝成功!");
19         }
20     }
21     public static void copy(File src, File target) throws IOException {
22         //1,在目标文件夹中创建原文件夹
23         File newDir = new File(target, src.getName());
24         newDir.mkdir();
25         //2,获取原文件夹中所有的文件和文件夹,存储在File数组中
26         File[] subFiles = src.listFiles();
27         //3,遍历数组
28         if(subFiles != null) {
29             for (File subFile : subFiles) {
30                 //4,如果是文件就用io流读写
31                 if(subFile.isFile()) {
32                     BufferedInputStream bis = new BufferedInputStream(new FileInputStream(subFile));
33                     BufferedOutputStream bos = new BufferedOutputStream
34                             (new FileOutputStream(new File(newDir,subFile.getName())));
35                     
36                     int b = 0;
37                     while((b = bis.read()) != -1) {
38                         bos.write(b);
39                     }
40                     
41                     bis.close();
42                     bos.close();
43                     //5,如果是文件夹就递归调用
44                 }else {
45                     copy(subFile,newDir);
46                 }
47             }
48         }
49     }
50     
51     public static File getDir() {
52         //1,创建键盘录入对象
53         Scanner sc = new Scanner(System.in);
54         System.out.println("请输入一个文件夹路径:");
55         //2,定义一个无限循环
56         while(true) {
57             //3,将键盘录入的结果存储并封装成File对象
58             String line = sc.nextLine();
59             File dir = new File(line);
60             //4,对File对象判断
61             if(!dir.exists()) {
62                 System.out.println("您录入的文件夹路径不存在,请重新录入:");
63             }else if(dir.isFile()) {
64                 System.out.println("您录入的是文件路径,请重新录入:");
65             }else {
66                 //5,将文件夹路径对象返回
67                 return dir;
68             }
69         }
70     }
71 }
View Code

 

六、小结

  1. 其实拷贝文件夹还有更加简单的方法,org.apache.commons.io.FileUtils工具类有一个方法copyDirectoryToDirectory(File source,File target)可以直接完成。具体代码如:FileUtils.copyDirectoryToDirectory(getDir(), getDir());

推荐阅读