Java面试宝典——算法与编程(三)

二.算法与编程


1、编写一个程序,将 a.txt 文件中的单词与 b.txt 文件中的单词交替合并到 c.txt
文件中,a.txt 文件中的单词用回车符分隔,b.txt 文件中用回车或空格进行分隔。
答:

packagecn.itcast;
 
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
 
public class MainClass{
     public static voidmain(String[] args) throws Exception{
         FileManager a= new FileManager("a.txt",new char[]{'n'});
         FileManager b= new FileManager("b.txt",new char[]{'n',' '}); 
         FileWriter c= new FileWriter("c.txt");
         String aWord= null;
         String bWord= null;
         while((aWord= a.nextWord()) !=null ){
             c.write(aWord+ "n");
             bWord= b.nextWord();
             if(bWord!= null)
             c.write(bWord+ "n");
         } 
 
         while((bWord= b.nextWord()) != null){
             c.write(bWord+ "n");
         } 
         c.close(); 
     }  
} 

class FileManager{ 
     String[] words =null;
     int pos = 0;
     publicFileManager(String filename,char[] seperators) throws Exception{
         File f = newFile(filename);
         FileReaderreader = new FileReader(f);
         char[] buf =new char[(int)f.length()];
         int len =reader.read(buf);
         Stringresults = new String(buf,0,len);
         String regex= null;
         if(seperators.length>1 ){
             regex= "" + seperators[0] + "|" + seperators[1];
         }else{
             regex= "" + seperators[0];
         } 
         words =results.split(regex);
     } 
 
     public StringnextWord(){
         if(pos ==words.length)
             returnnull;
         returnwords[pos++];
    }
} 


2、编写一个程序,将 d:\java 目录下的所有.java 文件复制到 d:\jad 目录下,并
将原来文件的扩展名从.java 改为.jad
(大家正在做上面这道题,网上迟到的朋友也请做做这道题,找工作必须能编写这些简单问
题的代码!)
答:listFiles 方法接受一个 FileFilter 对象,这个 FileFilter 对象就是过虑的策略对象,不
同的人提供不同的 FileFilter 实现,即提供了不同的过滤策略。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
public class Jad2Java {
     
     public static voidmain(String[] args) throws Exception {
         File srcDir =new File("java");
         if(!(srcDir.exists()&& srcDir.isDirectory()))
             thrownew Exception("目录不存在");
         File[] files= srcDir.listFiles(
             newFilenameFilter(){             
                 publicBoolean accept(File dir, String name) {
                     returnname.endsWith(".java");                 
                }
            }
         
         );
         
         System.out.println(files.length);
         File destDir= new File("jad");
         if(!destDir.exists())destDir.mkdir();
         for (File f:files){
             FileInputStream fis = new FileInputStream(f);
             StringdestFileName = f.getName().replaceAll("\.java$", ".jad");
             FileOutputStreamfos = new FileOutputStream(new 
                 File(destDir,destFileName));
             copy(fis,fos);
             
             fis.close();
             fos.close();             
        }  
    }
    private static voidcopy(InputStream ips,OutputStream ops) throws Exception{
         int len = 0;
         byte[] buf =new byte[1024];
         while((len =ips.read(buf)) != -1){
             ops.write(buf,0,len);             
        }
    }     
}
 

由本题总结的思想及策略模式的解析:
1.
class jad2java{
 1. 得到某个目录下的所有的 java 文件集合
 1.1 得到目录 File srcDir = newFile("d:\\java");
 1.2 得到目录下的所有 java 文件:File[] files =srcDir.listFiles(new 
MyFileFilter());
 1.3 只想得到.java 的文件: class MyFileFilterimplememyts FileFilter{
 publicboolean accept(File pathname){
 returnpathname.getName().endsWith(".java")
 } 
 } 
 
 2.将每个文件复制到另外一个目录,并改扩展名
 2.1 得到目标目录,如果目标目录不存在,则创建之
 2.2 根据源文件名得到目标文件名,注意要用正则表达式,注意.的转义。
 2.3 根据表示目录的File和目标文件名的字符串,得到表示目标文件的File。
 //要在硬盘中准确地创建出一个文件,需要知道文件名和文件的目
录。
 2.4 将源文件的流拷贝成目标文件流,拷贝方法独立成为一个方法,方法的
参数采用抽象流的形式。
 //方法接受的参数类型尽量面向父类,越抽象越好,这样适应面更
宽广。 

 
分析 listFiles 方法内部的策略模式实现原理

File[] listFiles(FileFilter filter){
     File[] files =listFiles();
     //ArraylistacceptedFilesList = new ArrayList();
     File[] acceptedFiles= new File[files.length];
     int pos = 0;
     for (File file:files){
         booleanaccepted = filter.accept(file);
         if(accepted){
             //acceptedFilesList.add(file);
             acceptedFiles[pos++]= file;             
        }
    }
    Arrays.copyOf(acceptedFiles,pos);
    //return(File[])accpetedFilesList.toArray();
}
 

3、编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截
取的字符串,但要保证汉字不被截取半个,如“我 ABC”,4,应该截取“我 AB”,
输入“我 ABCDEF”,6,应该输出“我 ABC”,而不是“我 ABC+汉的半个”。
答:
 首先要了解中文字符有多种编码及各种编码的特征。
 假设 n 为要截取的字节数。
 

public static void main(String[] args) throws Exception{
     String str ="我 a 爱中华 abc 我爱传智 def";
     String str ="我 ABC 汉";
     int num =trimGBK(str.getBytes("GBK"),5);
     System.out.println(str.substring(0,num));
 } 
 
 public static int trimGBK(byte[] buf,int n){
     int num = 0;
     booleanbChineseFirstHalf = false;
     for(inti=0;i


4、有一个字符串,其中包含中文字符、英文字符和数字字符,请统计和打印出
各个字符的个数。
答:哈哈,其实包含中文字符、英文字符、数字字符原来是出题者放的烟雾弹。

String content = “中国 aadf 的111萨 bbb 菲的 zz 萨菲”;
 
HashMap map = new HashMap();
for (int i=0;i

估计是当初面试的那个学员表述不清楚,问题很可能是:
如果一串字符如"aaaabbc 中国1512"要分别统计英文字符的数量,中文字符的数量,和数字
字符的数量,假设字符中没有中文字符、英文字符、数字字符之外的其他特殊字符。

int engishCount;
int chineseCount;
int digitCount;
for (int i=0;i=’0’&& ch<=’9’) 
     {         
         digitCount++         
    }     
      elseif((ch>=’a’&& ch<=’z’) || (ch>=’A’ && ch<=’Z’))
     {         
         engishCount++;         
    }else 
     {         
         chineseCount++;         
    }     
}
System.out.println(……………);

 
5、说明生活中遇到的二叉树,用 java 实现二叉树
这是组合设计模式。
我有很多个(假设10万个)数据要保存起来,以后还需要从保存的这些数据中检索是否存在某
个数据,(我想说出二叉树的好处,该怎么说呢?那就是说别人的缺点),假如存在数组中,
那么,碰巧要找的数字位于99999那个地方,那查找的速度将很慢,因为要从第1个依次往
后取,取出来后进行比较。平衡二叉树(构建平衡二叉树需要先排序,我们这里就不作考虑
了)可以很好地解决这个问题,但二叉树的遍历(前序,中序,后序)效率要比数组低很多,
原理如下图:
代码如下:

package com.huawei.interview;
 
publicclass Node {
     public int value;
     public Node left;
     public Node right;
     
     public void store(intvalue)
     {         
         if(valuethis.value)
         {             
             if(right ==null) 
             {                 
                 right = new Node();
                 right.value=value;                 
            } else
             {                 
                 right.store(value);                 
            }
        }
    }
    public Boolean find(intvalue)
    {
         System.out.println("happen" +this.value);
         if(value ==this.value)
         {             
             return true;
        }
          else if(value>this.value)
         {             
             if(right ==null)return false;             
             return right.find(value);             
        } else
         {             
             if(left ==null)returnfalse;             
             return left.find(value);             
        }
    }
     public void preList()
     {         
         System.out.print(this.value+ ",");
         if(left!=null)left.preList();
         if(right!=null) right.preList();         
    }
     public void middleList()
     {         
         if(left!=null)left.preList();
         System.out.print(this.value+ ",");
         if(right!=null)right.preList();
    }     
     public void afterList()
     { 
         if(left!=null)left.preList();
         if(right!=null)right.preList();
         System.out.print(this.value+ ",");
    }
     public static voidmain(String [] args)
     {         
         int [] data =new int[20];
         for (inti=0;i

-----------------又一次临场写的代码---------------------------

importjava.util.Arrays;
importjava.util.Iterator;
 
public class Node{
     private Node left;
     private Node right;
     private int value;
     //private int num;
     
     public Node(int value){
         this.value = value;         
    }     
     public void add(int value){         
         if(value > this.value)
         {             
             if(right != null)
             right.add(value);
              else 
             {                 
                 Node node = new Node(value);                 
                 right = node;                 
            }
        }         
         else{
             if(left != null)
             left.add(value);
              else 
             {                 
                 Node node = new Node(value);                 
                 left = node;
            }
        }
    }
     public Boolean find(int value){
         if(value == this.value) return true;
          else if(value > this.value){
             if(right == null) return false;
              else return right.find(value);             
        } else{
             if(left == null) return false;
              else return left.find(value);
        }
    }
     public void display(){
         System.out.println(value);
         if(left != null) left.display();
         if(right != null) right.display(); 
    }
    /*public Iterator iterator(){
 
 }*/     
     public static void main(String[] args){
         int[] values = new int[8];
         for (int i=0;i<8;i++){
             int num = (int)(Math.random() * 15);
             //System.out.println(num);
             //if(Arrays.binarySearch(values,num)<0)
             if(!contains(values,num))
             values[i] = num;
              else 
             i--;
        }
         System.out.println(Arrays.toString(values));         
         Node root = new Node(values[0]);
         for (int i=1;i

6、从类似如下的文本文件中读取出所有的姓名,并打印出重复的姓名和重复的
次数,并按重复次数排序:
1,张三,28
2,李四,35
3,张三,28
4,王五,35
5,张三,28
6,李四,35
7,赵六,28
8,田七,35
 
程序代码如下(答题要博得用人单位的喜欢,包名用该公司,面试前就提前查好该公司的网
址,如果查不到,现场问也是可以的。还要加上实现思路的注释):

package com.huawei.interview;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;

publicclass GetNameTest {

    /** 
     * @paramargs
     */
     public static voidmain(String[] args) {
         // TODO Auto-generated method stub
         //InputStream ips =GetNameTest.class.getResourceAsStream("/com/huawei/interview/info.txt");
         //用上一行注释的代码和下一行的代码都可以,因为 info.txt 与 GetNameTest 类在
        同一包下面,所以,可以用下面的相对路径形式
         
         Map results = new HashMap();
         InputStream ips = GetNameTest.class.getResourceAsStream("info.txt");
         BufferedReader in = newBufferedReader(new InputStreamReader(ips));
         String line = null;         
         try {             
             while((line=in.readLine())!=null) 
             {                 
                 dealLine(line,results);
            }
             sortResults(results);
        }
        catch (IOException e) {
             // TODO Auto-generated catchblock
             e.printStackTrace();
        }
    }
     static class User
     {         
         public String name;
         public Integer value;
         public User(String name,Integervalue)
         {             
             this.name = name;
             this.value = value;             
        }
         @Override
         public booleanequals(Object obj) {
             // TODO Auto-generated methodstub
             
             //下面的代码没有执行,说明往 treeset 中增加数据时,不会使用到 equals 方
            法。
             Boolean result =super.equals(obj);
             System.out.println(result);
             return result;             
        }
    }
     private static voidsortResults(Map results) {
         // TODO Auto-generated method stub
         TreeSet sortedResults =newTreeSet(
         new Comparator(){
             public intcompare(Object o1, Object o2) {
                 // TODOAuto-generated method stub
                 User user1 = (User)o1;
                 User user2 = (User)o2;                 
                /*如果 compareTo 返回结果0,则认为两个对象相等,新的对象不
会增加到集合中去
 * 所以,不能直接用下面的代码,否则,那些个数相同的其他姓名
就打印不出来。
 * */
                 
                 //returnuser1.value-user2.value;                 
                //returnuser1.valueuser2.value)
                 {                     
                     return 1;                     
                } else
                 {                     
                     returnuser1.name.compareTo(user2.name);
                }
            }
        }         
         );
         Iterator iterator =results.keySet().iterator();
         while(iterator.hasNext())
         {             
             String name = (String)iterator.next();
             Integer value =(Integer)results.get(name);
             if(value > 1)
             {                 
                 sortedResults.add(newUser(name,value));
            }
        }
         printResults(sortedResults);         
    }     
     private static voidprintResults(TreeSet sortedResults)
     {         
         Iterator iterator = sortedResults.iterator();
         while(iterator.hasNext())
         {             
             User user = (User)iterator.next();
             System.out.println(user.name +":" + user.value);             
        }
    }     
     public static voiddealLine(String line,Map map)
     {         
         if(!"".equals(line.trim()))
         {             
             String [] results =line.split(",");
             if(results.length == 3)
             {                 
                 String name = results[1];
                 Integer value =(Integer)map.get(name);
                 if(value ==null)value = 0;
                 map.put(name,value + 1);                 
            }
        }
    }
}
 

7、写一个 Singleton 出来。
第一种:饱汉模式

public classSingleTon {
     private SingleTon(){
     } 
 
     //实例化放在静态代码块里可提高程序的执行效率,但也可能更占用空间 
     private final static SingleTon instance =new SingleTon();
     public static SingleTon getInstance(){
         return instance;
     } 
} 

 
第二种:饥汉模式

public classSingleTon {
     private SingleTon(){} 
     private static instance = null;//newSingleTon();
 
     public static synchronized SingleTongetInstance(){
         if(instance == null)
             instance = new SingleTon();
         return instance;
     } 
} 


第三种:用枚举
 

public enum SingleTon{
     ONE;
 
 } 

第三:更实际的应用(在什么情况用单例)

public classSequenceGenerator{
     //下面是该类自身的业务功能代码
     private int count = 0; 
     public synchronized int getSequence(){
         ++count;
     }  
     //下面是把该类变成单例的代码
     private SequenceGenerator(){}
     private final static instance = newSequenceGenerator();
     public static SingleTon getInstance(){
         return instance;
     } 
} 

第四:
 

public class MemoryDao
 { 
     private HashMap map = new HashMap(); 
     publicvoid add(Student stu1){
         map.put(SequenceGenerator.getInstance().getSequence(),stu1);
     }  
     //把 MemoryDao 变成单例
 } 

 
Singleton 模式主要作用是保证在 Java 应用程序中,一个类 Class 只有一个实例存在。
一般 Singleton 模式通常有几种种形式: 
第一种形式: 定义一个类,它的构造函数为 private 的,它有一个 static 的 private 的该类变
量,在类初始化时实例话,通过一个 public 的 getInstance 方法获取对它的引用,继而调用其
中的方法。

public class Singleton {
private Singleton(){}
     //在自己内部定义自己一个实例,是不是很奇怪?
     //注意这是 private 只供内部调用
     private staticSingleton instance = new Singleton();
     //这里提供了一个供外部访问本 class 的静态方法,可以直接访问 
     public staticSingleton getInstance() {
         return instance;
     } 
 } 

 第二种形式: 

public class Singleton {
    private static Singleton instance = null;
    public static synchronized Singleton getInstance() {
        //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次 
        //使用时生成实例,提高了效率!
        if (instance==null)
            instance=new Singleton();
         return instance;
     } 
} 

其他形式: 
定义一个类,它的构造函数为 private 的,所有方法为 static 的。
一般认为第一种形式要更加安全些


8、递归算法题 1 
一个整数,大于0,不用循环和本地变量,按照 n,2n,4n,8n 的顺序递增,当值大于5000
时,把值按照指定顺序输出来。
例:n=1237
则输出为:
1237,
2474,
4948,
9896,
9896,
4948,
2474,
1237,
提示:写程序时,先致谢按递增方式的代码,写好递增的以后,再增加考虑递减部分。
 

public static void doubleNum(int n)
 { 
     System.out.println(n);
     if(n<=5000)
         doubleNum(n*2);
     System.out.println(n); 
 } 
Gaibaota(N) = Gaibaota(N-1) + n


9、递归算法题 2 
第1个人10,第2个比第1个人大2岁,依次递推,请用递归方式计算出第8个人多大?

package cn.itcast;
 
import java.util.Date;
 
publicclass A1 { 
    public static voidmain(String [] args)
    { 
        System.out.println(computeAge(8));
    } 
 
    public static int computeAge(intn)
    { 
        if(n==1)return 10;
        returncomputeAge(n-1) + 2;
    } 
} 
 
public static voidtoBinary(int n,StringBuffer result)
{  
    if(n/2 != 0)
    toBinary(n/2,result);
    result.append(n%2); 
} 


10、排序都有哪几种方法?请列举。用 JAVA 实现一个快速排序。
本人只研究过冒泡排序、选择排序和快速排序,下面是快速排序的代码:

public class QuickSort {
    /**
    * 快速排序
    * @param strDate
    * @param left
    * @param right
    */
    public void quickSort(String[] strDate,int left,int right){
        String middle,tempDate;
        int i,j;
        i=left;
        j=right;
        middle=strDate[(i+j)/2];
        do{
            while(strDate[i].compareTo(middle)<0&& i0&& j>left)
            j--;
            //找出右边比中间值小的数
            if(i<=j){
                //将左边大的数和右边小的数进行替换
                tempDate=strDate[i];
                strDate[i]=strDate[j];
                strDate[j]=tempDate;
                i++;
                j--;                 
            }             
        }
        while(i<=j);
        //当两者交错时停止
        if(ileft){
            quickSort(strDate,left,j);
        }         
    }
     
    /**
     * @param args
     */
    public static void main(String[] args){
        String[] strVoid=newString[]{"11","66","22","0","55","22","0","32"};
        QuickSort sort=new QuickSort();
        sort.quickSort(strVoid,0,strVoid.length-1);
        for (int i=0;i

11、有数组 a[n],用 java 代码将数组元素顺序颠倒
//用下面的也可以
//for(inti=0,int j=a.length-1;i  

importjava.util.Arrays;
 
public classSwapDemo{     
     public static void main(String[] args){
         int [] a = new int[]{
             (int)(Math.random() *1000),
             (int)(Math.random() * 1000),
             (int)(Math.random() *1000),
             (int)(Math.random() *1000), 
             (int)(Math.random() * 1000)          
        }
        ; 
         System.out.println(a);
         System.out.println(Arrays.toString(a));
         swap(a);
         System.out.println(Arrays.toString(a));
    }
     public static void swap(int a[]){
         int len = a.length;
         for (int i=0;i


12.金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一
千零一拾一元整)输出。
去零的代码:
 returnsb.reverse().toString().replaceAll("零[拾佰仟]","零").replaceAll("零+万","万
").replaceAll("零+元","元").replaceAll("零+","零");
 

public class RenMingBi {
    /**
     * @param args add by zxx ,Nov 29, 2008
     */
     private static finalchar[] data = new char[]{
         '零','壹','贰','叁','肆','伍','陆','柒','捌','玖' 
     };
     private static finalchar[] units = new char[]{
         '元','拾','佰','仟','万','拾','佰','仟','亿' 
     };
     public static voidmain(String[] args) {
         // TODOAuto-generated method stub
         System.out.println(
         convert(135689123));         
    }
     public static Stringconvert(int money)
     {         
         StringBuffersbf = new StringBuffer();
         int unit = 0;
         while(money!=0)
         {             
             sbf.insert(0,units[unit++]);
             intnumber = money%10;
             sbf.insert(0,data[number]);
             money/= 10;             
        }
        returnsbf.toString();         
    }     
}
 

 

 

------------------------------------------------------------------------------

上一篇:Java面试宝典——基础部分(二)

下一篇:Java面试宝典——html&JavaScript&ajax 部分(四)

------------------------------------------------------------------------------
 

你可能感兴趣的:(Java面试宝典)