您的位置:首页 > 职场人生

2014百度实习生面试题(部分)具体解释

2014-06-23 09:07 190 查看
这阵子同学投实习,面试了百度,由于我还没有投实习所以仅仅能事后问他都有哪些面试题。他记得的大概几个,字符串翻转、字符替代、一亿数据中找出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)+"\n").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);

}


[align=left]然后对每个数组里面的数採用插入算法:[/align]

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;
}

}


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

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();
}
}


八皇后问题的另外两种实现:

[align=justify]循环方式:[/align]
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("\n 详细的图演示样例如以下图所看到的: ");
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+"种解法");
}

}


[align=justify]递归方式:[/align]
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("\n 详细的图演示样例如以下图所看到的: ");
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函数的打印结果是:

[align=left]10 5 7[/align]
[align=left]10 12 [/align]

OK!GOOD LUCK!小伙伴们加油!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: