zoukankan      html  css  js  c++  java
  • 2014百度实习生面试题(部分)具体解释

    这阵子同学投实习,面试了百度,由于我还没有投实习所以仅仅能事后问他都有哪些面试题。他记得的大概几个,字符串翻转、字符替代、一亿数据中找出100个最大数(似乎有内存限制)、八皇后问题和二叉树查找类似的问题。具体记不大清了,这些算法题都还是算是比較经典的,网上也有非常多具体解释,我也试着想想这些问题怎么解,针对这几个题解法罗列于此,希望对童鞋们有所帮助。如有不正确的地方,欢迎指正。
    1、字符串翻转。
    解法:七种java实现方法:
    import java.util.Stack;
    public class StringReverse {
    
    //折半递归
    public static String reverse1(String s) {
      int length = s.length();
      if (length <= 1)
       return s;
      String left = s.substring(0, length / 2);
      String right = s.substring(length / 2, length);
      return reverse1(right) + reverse1(left);
    }
    
    //依次取字符放最前拼接
    public static String reverse2(String s) {
      int length = s.length();
      String reverse = "";
      for (int i = 0; i < length; i++)
       reverse = s.charAt(i) + reverse;
      return reverse;
    }
    
    //字符数组
    public static String reverse3(String s) {
      char[] array = s.toCharArray();
      String reverse = "";
      for (int i = array.length - 1; i >= 0; i--)
       reverse += array[i];
    
      return reverse;
    }
    
    //用StringBuffer的reverse方法
    public static String reverse4(String s) {
      return new StringBuffer(s).reverse().toString();
    }
    
    //对称交换
    public static String reverse5(String orig) {
      char[] s = orig.toCharArray();
      int n = s.length - 1;
      int halfLength = n / 2;
      for (int i = 0; i <= halfLength; i++) {
       char temp = s[i];
       s[i] = s[n - i];
       s[n - i] = temp;
      }
      return new String(s);
    }
    
    //
    public static String reverse6(String s) {
    
      char[] str = s.toCharArray();
    
      int begin = 0;
      int end = s.length() - 1;
    
      while (begin < end) {
       str[begin] = (char) (str[begin] ^ str[end]);
       str[end] = (char) (str[begin] ^ str[end]);
       str[begin] = (char) (str[end] ^ str[begin]);
       begin++;
       end--;
      }
    
      return new String(str);
    }
    
    //利用栈的先进后出特点
    public static String reverse7(String s) {
      char[] str = s.toCharArray();
      Stack<Character> stack = new Stack<Character>();
      for (int i = 0; i < str.length; i++)
       stack.push(str[i]);
    
      String reversed = "";
      for (int i = 0; i < str.length; i++)
       reversed += stack.pop();
    
      return reversed;
    }
    
    }

    2、字符串替代方法:例非常长的字符串中若干个空格,替换为逗号“,”。
    解法:(1)word等文本编辑工具CTRL+F进行查找替换:【比較笨,适合没有编程环境的电脑】
    步骤一:在替换中“查找内容”填两个连续空格“  ”,在“替换为”填上一个空格“ ”。狂点“所有替换”直到“0处替换”。这时所有的抖个空格都变成了一个空格。
    步骤二:在“查找内容”填上一个空格“ ”,在“替换为”填上须要终于替换的字符如题中的逗号“,”。完毕。
    (2)在linux操作系统中可採用shell脚本处理:【方便快捷的好方法啊!!!】
    语句:sed '/ +/s//,/g' file1.txt>file2.txt  
    解释:用sed语句将文件file1.txt中的若干个空格替换为逗号“,”,存储在文件file2.txt中。
    (3)java编程实现:
    package com.melina;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStreamReader;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class Preprocess {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            String regEx = "['   ']+"; // 一个或多个空格
    
            Pattern p = Pattern.compile(regEx);
    
            try {
                String encoding = "gbk"; // 字符编码(可解决中文乱码问题 )
                File file = new File("E:/hadoop/bill.txt");
                if (file.isFile() && file.exists()) {
                    InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
                    BufferedReader bufferedReader = new BufferedReader(read);
                   
                    FileOutputStream out = null;  
    
                    out = new FileOutputStream(new File("E:/hadoop/bill1.txt"));
                   
                    String lineTXT = null;
                    lineTXT = bufferedReader.readLine();//去掉第一行 的字段名
                    int count = 0;
                 
                    while ((lineTXT = bufferedReader.readLine()) != null) {
                        //count += 1;
                        Matcher m = p.matcher(lineTXT);
                        //String str = count + "," + m.replaceAll(",").trim();//输出行号
                        String str = m.replaceAll(",").trim(); //将若干个空格替换为逗号“,”
                        System.out.println(str.substring(0, str.length()-1));
                        //out.write((str.substring(0, str.length()-1)+"
    ").getBytes());
                        if(count == 0) {
                             out.write((str.substring(0, str.length()-1)).getBytes());
                        } else {
                             out.write(13);
                             out.write((str.substring(0, str.length()-1)).getBytes());
                        }
                        count += 1;                  
                    }
                    read.close();
                    out.close();
                } else {
                    System.out.println("找不到指定的文件!");
                }
            } catch (Exception e) {
                System.out.println("读取文件内容操作出错");
                e.printStackTrace();
            }
        }
    
    }



    3、从一亿数据中找出最大的100个数。
    解法:(1)将一亿个数装在数组里面直接用java的各种排序插入算法实现:
    注意内存溢出的问题,能够设置JVM
    先生成包括一亿个随机数的数组:
     
    int[] test =new int[100000000];//1亿个数字
                  Random r = new Random();
                   for(int i=0;i<test.length;i++){
                         test[i] = r.nextInt(test. length * 2);
                         
                  }


    然后对每个数组里面的数採用插入算法:
    for(int i=0;i<test.length;i++){
            insert(test[i]);
    }

    几个不同的插入算法:
    public void insert(int a){
                   //维持数组从大到小排序
                   for(int i=0;i<data.length;i++){
                          if(a>data [i]){//a放到data[i].同一时候i開始到100,后移
                                for(int j=data .length -1 ;j>i;j--){
                                       data[j] = data[j-1];
                               }
                                data[i] = a;
                                break;
                         }
                  }
                   //printResult();
           }
            public void insert1(int a){
                   //由于数组已经是从大到小排序,因此从尾部到头部開始,大的插入,小的话则继续
                   if(a < data [data .length - 1]) return;//比最小的还小则退出
                   for(int i =0;i<data.length; i++){
                          if(a > data [i]){
                                for(int j=data .length -1 ;j>i;j--){
                                       data[j] = data[j-1];
                               }
                                data[i] = a;
                                break;
                         }
                  }
           }
           
            public void insert2(int a){ //linkNode插入
                  LinkNode t = sdata;
                  LinkNode pre = null;
                   int idx = 0;
                   while(t!= null ){
                         idx++;
                          if(idx >= 100){
                               t.setNext( null);
                                break;
                         }
                          if(a > t.getData()){
                               LinkNode temp = new LinkNode(a);
                               temp.setNext(t);
                                if(sdata == t)sdata = temp;
                                if(pre != null )pre.setNext(temp);
                                //printLinkResult();
                                break;
                         }
                         pre = t;
                         t = t.getNext();
                         
                          //printLinkResult();
                         
                  }                       
           }


    当中链表的定义:

    public class LinkNode {
            private int data ;
            private LinkNode next ;
            public LinkNode(int data) {
                   this.data = data;
                   this.next = null;
           }
            public LinkNode getNext() {
                   return next ;
           }
            public void setNext(LinkNode next) {
                   this.next = next;
           }
            public int getData() {
                   return data ;
           }
            public void setData(int data) {
                   this.data = data;
           }
           
    }


    (2)假设内存有限,一亿的数据无法直接所有放在内存中处理,这时就须要採取另外的措施了,一部分一部分地加到内存处理。
    (3)如果这一亿个数能够导入数据库中,使用sql语句:【还没有尝试,不知是否可行或者效率怎样】
    select * from table order by 字段名 desc limit 100;
    (4)如果这一亿数据在文件里,mapreduce程序处理:【待尝试】

    4、八皇后问题
    解法:【这个问题已经非常经典了,主要是有循环和递归方法。代码量大,主要摘抄自网络】
    /**
      问题描写叙述:在一个8×8国际象棋盘上,有8个皇后,每一个皇后占一格;
      要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。
      问共同拥有多少种不同的方法。
      基本思路:
      定义一个用来存放解的一维数组int[] cellpos = new int[9],为直观起见,约定下标从1開始。
      数组的下标表示皇后所在的列,值表示皇后当前列所在的行。
      定义一个列指示器pointer,用于指示当前程序已经求解到第几列。
      先将pointer置为1,cellpos[1]置为1,即程序从第一列第一行開始求解。
      当cellpos[1]>8时表示已经将解所有都求出来了.
      为了降低部分时间复杂度,我们能够再给第二列赋一个初值,大家能够想想这个初值应该是多少.
      给第二列赋完初值后,列指示器pointer应该等于3,即程序从第三列開始扫描,
      此时i从第三列的第一行一直扫描到第8行.当皇后位于i行时,比方说如今第一列第一
      行有一个皇后,第二列第三行有一个皇后,那么i肯定不能等于1,2,3,4.
      然后如果cellpos[3] = 5,pointer++,列指示器跳到下一列,继续扫描,当pointer==8时,
      说明已经扫描完了,当然扫描的时候i可能>8说明没有解,这时候就得加一个推断, 我们如果找到了最后一列的解,
      就将这组解打印出来,然后pointer--,回到倒数第二列,并将cellpos[pointer]++,
      由于倒数第二列的前面几行已经扫描过了.这时候别忘了清理最后一列,由于倒数第二列
      的皇后位置已经变了,那么最后一列应该又一次从第一行開始扫描,想想为什么.
      继续扫描解,当倒数第二列皇后位置也>8时,pointer--,回到倒数第三列,当然要
      cellpos[pointer]++,而且将后面几列清理干净.  程序一直这样循环的执行,
      直到cellpos[1]>8.
    */
    public class Queen {
         //定义两个int型变量,用于下面循环程序。
         private int i,k;
         //列指示器
         private int pointer = 1;
         //解
         int[] cellpos = new int[9];
        public Queen() {
             cellpos[pointer] = 1;
             cellpos[2] = 3;
             pointer = 3;
             //给第二列之后的列赋一个初值1,由于默认是0,而我们约定的是从1開始.
             clean(2);
            
             while(cellpos[1] <= 8) {
                  /**
                  * 特殊点第一列,这里不写cellpos[pointer]++;
                  * 是由于后面的程序中已经加过了.
                  */
                  //if(pointer == 1) {
                       //cellpos[pointer]++;
                       //pointer++;
                       //continue;
                  //}
                 
                  /**
                  * 特殊点第八行,这里为什么还要加一个推断呢
                  * 或许你会问后面不是有i>8推断吗?试想一下,当倒数第二列
                  * 正好等于8,求完解后,回到倒数第二列,
                  * 而且后面的程序会使倒数第二列加1,如今还觉得它多余么.
                  */
                  if(cellpos[pointer]>8) {
                       pointer--;
                       cellpos[pointer]++;
                       //清理
                       clean(pointer);
                       continue;
                  }
                 
                  /**
                  * 扫描
                  */
                  for(i=cellpos[pointer]; i<=8; i++)
                       if(canStay(i)) break;
                 
                 
                  if(i>8) {
                       pointer--;
                       cellpos[pointer]++;
                       //清理
                       clean(pointer);
                       continue;
                  }else{
                       cellpos[pointer] = i;
                  }
                 
                  if(pointer==8) {
                       //将解打印出来
                       printQueen();
                       pointer--;
                       cellpos[pointer]++;
                       //清理
                       clean(pointer);
                  }else{
                       pointer++;
                  }
             }
        }
       
        private boolean canStay(int ci) {
             //行扫描,推断同一行是否有其他皇后.
             for(k=1; k<pointer; k++)
                  if(cellpos[k]==ci) return false;
             //对角线扫描,推断对角线上是否有其他皇后.注意有两条对角线.
             for(k=1; k<pointer; k++)
                  if((ci==cellpos[k]+(pointer-k)) ||
                       (ci==cellpos[k]-(pointer-k)))
                            return false;
             return true;
        }
       
        private void clean(int pointer) {
             for(k=pointer+1; k<9; k++)
                  cellpos[k] = 1;
        }
       
        private void printQueen() {
             for(k = 1; k<9; k++) {
                  System.out.print(""+cellpos[k]);
                  if(k!=8)
                       System.out.print(",");
             }
             System.out.println();
        }
       
        public static void main(String[] args) {
             new Queen();
        }
    }



    八皇后问题的另外两种实现:
    循环方式:
    package EightQueens;
    
    public class EightQueensNotRecursive {
    private static final boolean AVAILABLE = true;
    private int squares = 8, norm = squares - 1;
    private int positionInRow[] = new int[squares];
    private int p=-1;
    private boolean[] rows = new boolean[squares];
    private boolean[] column = new boolean[squares];
    private boolean[] leftDiagonal = new boolean[2 * squares - 1];
    private boolean[] rightDiagonal = new boolean[2 * squares - 1];
    private static int howMany = 0;
    
    public EightQueensNotRecursive() {
    // To complete the initialization work for the
    // column,leftDiagonal,rigthDiagonal.
    for (int i = 0; i < squares; i++) {
    rows[i] = AVAILABLE;
    column[i] = AVAILABLE;
    positionInRow[i] = -1;
    }
    for (int i = 0; i < 2 * squares - 1; i++) {
    leftDiagonal[i] = AVAILABLE;
    rightDiagonal[i] = AVAILABLE;
    }
    
    }
    
    public void printResults(int[] columns) {
    int row, col;
    System.out.println(" 八皇后问题的第 " + howMany + " 种解法");
    System.out.print(" 八皇后问题的结果为: ");
    for (int e : columns) {
    System.out.print(e);
    }
    System.out.println("
     详细的图演示样例如以下图所看到的: ");
    for (row = 0; row < squares; row++) {
    for (col = 0; col < squares; col++) {
    if (col == positionInRow[row]) {
    System.out.print("@");
    } else {
    System.out.print("*");
    }
    }
    System.out.println();
    }
    System.out.println();
    }
    
    public void putQueen()
    {
    int row=0, col;
    while (true)
    {
    for (col = p + 1; col < squares; col++)
    {
    if(rows[row]==AVAILABLE&&column[col]==AVAILABLE&&leftDiagonal[row+col]==AVAILABLE&&rightDiagonal[row-col+norm]==AVAILABLE)
    {
    break;
    }
    }
    //在当前的行里面找到了能够放置皇后的位置
    if(col<squares)
    {
    rows[row]=!AVAILABLE;
    column[col]=!AVAILABLE;
    leftDiagonal[row+col]=!AVAILABLE;
    rightDiagonal[row-col+norm]=!AVAILABLE;
    positionInRow[row]=col;
    p=col;
    }else//假设当前行没办反放置皇后了,那么回溯
    {
    if(row>0)//到前一行
    {
    row--;
    p=positionInRow[row];
    rows[row]=AVAILABLE;
    column[p]=AVAILABLE;
    leftDiagonal[row+p]=AVAILABLE;
    rightDiagonal[row-p+norm]=AVAILABLE;
    positionInRow[row]=-1;
    continue;
    }else
    {
    break;
    }
    }
    if(row==squares-1)
    {
    howMany+=1;
    printResults(positionInRow);
    p=positionInRow[row];
    rows[row]=AVAILABLE;
    column[p]=AVAILABLE;
    leftDiagonal[row+p]=AVAILABLE;
    rightDiagonal[row-p+norm]=AVAILABLE;
    positionInRow[row]=-1;
    continue;
    }
    else
    {
    row++;
    p=-1;
    continue;
    }
    }
    }
    public static void main(String args[])
    {
    EightQueensNotRecursive eightQueens=new EightQueensNotRecursive();
    eightQueens.putQueen();
    System.out.println(" 皇后问题一共同拥有 "+howMany+"种解法");
    }
    
    }



    递归方式:
    package EightQueens;
    
    public class EightQueensRecursive {
    private static final boolean AVAILABLE=true;
    private int squares=8,norm=squares-1;
    private int positionInRow[]=new int[squares];
    private boolean[] column=new boolean[squares];
    private boolean[] leftDiagonal=new boolean[2*squares-1];
    private boolean[] rightDiagonal=new boolean[2*squares-1];
    private static int howMany=0;
    public EightQueensRecursive(){
    //To complete the initialization work for the column,leftDiagonal,rigthDiagonal.
    for(int i=0;i<squares;i++){
    column[i]=AVAILABLE;
    positionInRow[i]=-1;
    }
    for(int i=0;i<2*squares-1;i++){
    leftDiagonal[i]=AVAILABLE;
    rightDiagonal[i]=AVAILABLE;
    }
    }
    public void printResults(int[] columns){
    int row,col;
    System.out.println(" 八皇后问题的第 "+howMany+" 种解法");
    System.out.print(" 八皇后问题的结果为: ");
    for(int e:columns){
    System.out.print(e);
    }
    System.out.println("
     详细的图演示样例如以下图所看到的: ");
    for(row=0;row<squares;row++){
    for(col=0;col<squares;col++){
    if(col==positionInRow[row]){
    System.out.print("@");
    }else{
    System.out.print("*");
    }
    }
    System.out.println();
    }
    System.out.println();
    }
    public void putQueen(int row){
    //假设前面已经得到了一个可行解
    for(int i=0;i<squares;i++)
    {
    if(row>squares-1) break;
    if(column[i]==AVAILABLE&&leftDiagonal[row+i]==AVAILABLE&&rightDiagonal[row-i+norm]==AVAILABLE)
    {
    positionInRow[row]=i;
    column[i]=!AVAILABLE;
    leftDiagonal[row+i]=!AVAILABLE;
    rightDiagonal[row-i+norm]=!AVAILABLE;
    if(row<squares-1){
    putQueen(row+1);
    }else
    {
    howMany+=1;
    printResults(positionInRow);
    }
    column[i]=AVAILABLE;
    leftDiagonal[row+i]=AVAILABLE;
    rightDiagonal[row-i+norm]=AVAILABLE;
    }
    }
    }
    public static void main(String args[]){
    EightQueensRecursive eightQueens=new EightQueensRecursive();
    eightQueens.putQueen(0);
    System.out.println(" 皇后问题一共找到了 "+howMany+"组解。");
    }
    }


    5、二叉树路径查找,并打印路径。
    解法:直接上代码,两个java文件:
    createBTree.java:
    package cn.melian.binaryTree;
    
    import java.util.Stack;
    import java.util.StringTokenizer;
    
    public class createBTree {
           
            //创建一棵二叉树
            public static BinaryTree createBTree(BinaryTree tree, StringTokenizer tokenizer){
                   if (tokenizer.hasMoreTokens()){
                         String str_data = tokenizer.nextToken();
                         tree = new BinaryTree();
                          if (str_data.equals("#" )){
                                return null;
                         }                    
                         tree. data = Integer. parseInt(str_data); //将值赋给节点
                         tree. leftnode = createBTree(tree. leftnode, tokenizer);
                         tree. rightnode = createBTree(tree. rightnode , tokenizer);
                          return tree;
                  }
                   return null;         
           }
           
            //搜索和为指定值得全部路径并打印出来
            public static void searchPrintTree( int value, int sum, BinaryTree tree, Stack<Integer> stack){
                   if (null != tree){
                         sum += tree. data;
                         stack.push(tree. data);
                          if (sum == value && tree.leftnode == null && tree. rightnode == null ){
                                for (int i:stack){
                                    System. out .print(i+" " );
                               }
                               System. out .println();
                         }
                          searchPrintTree(value, sum, tree. leftnode, stack);
                          searchPrintTree(value, sum, tree. rightnode, stack);
                         stack.pop();
                  }
           }
           
           
            //main函数
            public static void main(String[] args){
                   int value = 22;
                   int sum = 0;
                  String str_in = "10 5 4 # # 7 # # 12 # #" ;
                   //String[] str_arr = str_in.split(" ");
                  StringTokenizer tokenizer = new StringTokenizer(str_in, " " );
                  BinaryTree tree = new BinaryTree();
                  Stack<Integer> stack = new Stack<Integer>();
                  tree = createBTree(tree, tokenizer);
                   searchPrintTree(value, sum, tree, stack);
           }
           
    }


    二叉树的定义:
    BinaryTree.java:
    package cn.melian.binaryTree;
    
    public class BinaryTree {
            public int data ;
            public BinaryTree leftnode ;
            public BinaryTree rightnode ;
    }



    如上面main函数的打印结果是:
    10 5 7
    10 12 

    OK!GOOD LUCK!小伙伴们加油!




  • 相关阅读:
    [知识点]计算几何I——基础知识与多边形面积
    [旧版][知识点]SPFA算法
    [旧版][知识点]A*搜索(启发式搜索)
    [知识点]线段树
    [小工具]ChemistryHelper
    [考试]20150314
    [知识点]Cantor展开
    [旧版][知识点]拓扑排序
    [无效]网络流之Dinic算法
    [SCOI2005]扫雷Mine
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3803399.html
Copyright © 2011-2022 走看看