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!小伙伴们加油!




  • 相关阅读:
    【算法学习笔记】76.DFS 回溯检测 SJTU OJ 1229 mine
    【算法学习笔记】75. 动态规划 棋盘型 期望计算 1390 畅畅的牙签盒(改)
    【算法学习笔记】74. 枚举 状态压缩 填充方案 SJTU OJ 1391 畅畅的牙签袋(改)
    【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人
    【算法学习笔记】72.LCS 最大公公子序列 动态规划 SJTU OJ 1065 小M的生物实验1
    【算法学习笔记】71.动态规划 双重条件 SJTU OJ 1124 我把助教团的平均智商拉低了
    【算法学习笔记】70.回文序列 动态规划 SJTU OJ 1066 小M家的牛们
    【算法学习笔记】69. 枚举法 字典序处理 SJTU OJ 1047 The Clocks
    【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
    【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3803399.html
Copyright © 2011-2022 走看看