北京春雨天下软件公司的面试题
今天没事,请了一天的假,跑到其他公司去面试了,那个公司的前台妹妹长得还可以呀!,不多说了先来看一下三道笔试题,全部是算法题,可以使用c和java实现的:本人使用的是java语言实现的:
第一题:单链表的反转(一种是采用递归的方式,一种是循环的方式)
package com.chunyu.interview; public class ReverseNode { public static void main(String[] args){ Node head = new Node("head"); Node first = new Node("first"); Node second = new Node("second"); Node third = new Node("third"); Node forth = new Node("forth"); head.setNextNode(first); first.setNextNode(second); second.setNextNode(third); third.setNextNode(forth); forth.setNextNode(null); Node reverseHead = reverse(head); while(reverseHead != null){ System.out.print(reverseHead.getVal()+","); reverseHead = reverseHead.getNextNode(); } } /** * 递归,在反转当前节点之前先反转后续节点 */ public static Node reverse(Node head) { if (null == head || null == head.getNextNode()) { return head; } Node reversedHead = reverse(head.getNextNode()); head.getNextNode().setNextNode(head); head.setNextNode(null); return reversedHead; } /** * 遍历,将当前节点的下一个节点缓存后更改当前节点指针 * */ public static Node reverse2(Node head) { if (null == head) { return head; } Node pre = head; Node cur = head.getNextNode(); Node next; while (null != cur) { next = cur.getNextNode(); cur.setNextNode(pre); pre = cur; cur = next; } //将原链表的头节点的下一个节点置为null,再将反转后的头节点赋给head head.setNextNode(null); head = pre; return head; } static class Node{ private Node node; private String val; public Node(String val){ this.val = val; } public void setVal(String val){ this.val = val; } public String getVal(){ return val; } public void setNextNode(Node node){ this.node = node; } public Node getNextNode(){ return node; } } }
第二题:查找到两个升序排列的数组中相同的元素(开始的时候使用的是双层循环遍历做的,但是回来想一想,既然是升序的数组,肯定有用处的,可惜当时没想到呀!):
package com.chunyu.interview; import java.util.ArrayList; public class FindSameElement{ public static void main(String[] args) { ArrayList<Integer> A = new ArrayList<Integer>(); A.add(1); A.add(2); A.add(4); A.add(6); A.add(18); A.add(30); ArrayList<Integer> B = new ArrayList<Integer>(); B.add(2); B.add(5); B.add(7); B.add(18); B.add(27); B.add(30); ArrayList<Integer> C = new ArrayList<Integer>(); int aPointer = 0; int bPointer = 0; while(aPointer<A.size() && bPointer<B.size()){ int tempA = A.get(aPointer); int tempB = B.get(bPointer); if(tempA == tempB){ C.add(tempA); aPointer++; bPointer++; }else if(tempA>tempB){ bPointer++; }else{ aPointer++; } } for(int i=0;i<C.size();i++){ System.out.print(C.get(i)+","); } } }
第三题:求表达式的值(这道题只写了一半,这个是回来的时候自己在电脑上写的):
package com.chunyu.interview; import java.util.Collections; import java.util.Stack; public class CalculateExpression { private Stack<String> postfixStack = new Stack<String>();//后缀式栈 private Stack<Character> opStack = new Stack<Character>();//运算符栈 private int [] operatPriority = new int[] {0,3,2,1,-1,1,0,2};//运用运算符ASCII码-40做索引的运算符优先级 public static void main(String[] args) { CalculateExpression cal = new CalculateExpression(); String s = "5+12*4-4"; double result = cal.calculate(s); System.out.println(result); } /** * 按照给定的表达式计算 * @param expression 要计算的表达式 * @return */ public double calculate(String expression) { Stack<String> resultStack = new Stack<String>(); prepare(expression); Collections.reverse(postfixStack);//将后缀式栈反转 String firstValue ,secondValue,currentValue;//参与计算的第一个值,第二个值和算术运算符 while(!postfixStack.isEmpty()) { currentValue = postfixStack.pop(); if(!isOperator(currentValue.charAt(0))) {//如果不是运算符则存入操作数栈中 resultStack.push(currentValue); } else {//如果是运算符则从操作数栈中取两个值和该数值一起参与运算 secondValue = resultStack.pop(); firstValue = resultStack.pop(); String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0)); resultStack.push(tempResult); } } return Double.valueOf(resultStack.pop()); } /** * 数据准备阶段将表达式转换成为后缀式栈 * @param expression */ private void prepare(String expression) { opStack.push(',');//运算符放入栈底元素逗号,此符号优先级最低 char[] arr = expression.toCharArray(); int currentIndex = 0;//当前字符的位置 int count = 0;//上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值 char currentOp ,peekOp;//当前操作符和栈顶操作符 for(int i=0;i<arr.length;i++) { currentOp = arr[i]; if(isOperator(currentOp)) {//如果当前字符是运算符 if(count > 0) { postfixStack.push(new String(arr,currentIndex,count));//取两个运算符之间的数字 } peekOp = opStack.peek(); if(currentOp == ')') {//遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号 while(opStack.peek() != '(') { postfixStack.push(String.valueOf(opStack.pop())); } opStack.pop(); } else { while(currentOp != '(' && peekOp != ',' && compare(currentOp,peekOp) ) { postfixStack.push(String.valueOf(opStack.pop())); peekOp = opStack.peek(); } opStack.push(currentOp); } count = 0; currentIndex = i+1; } else { count++; } } if(count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {//最后一个字符不是括号或者其他运算符的则加入后缀式栈中 postfixStack.push(new String(arr,currentIndex,count)); } while(opStack.peek() != ',') { postfixStack.push(String.valueOf( opStack.pop()));//将操作符栈中的剩余的元素添加到后缀式栈中 } } /** * 判断是否为算术符号 * @param c * @return */ private boolean isOperator(char c) { return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' ||c == ')'; } /** * 利用ASCII码-40做下标去算术符号优先级 * @param cur * @param peek * @return */ public boolean compare(char cur,char peek) {// 如果是peek优先级高于cur,返回true,默认都是peek优先级要低 boolean result = false; if(operatPriority[(peek)-40] >= operatPriority[(cur) - 40]) { result = true; } return result; } /** * 按照给定的算术运算符做计算 * @param firstValue * @param secondValue * @param currentOp * @return */ private String calculate(String firstValue,String secondValue,char currentOp) { String result = ""; switch(currentOp) { case '+': result = String.valueOf(ArithHelper.add(firstValue, secondValue)); break; case '-': result = String.valueOf(ArithHelper.sub(firstValue, secondValue)); break; case '*': result = String.valueOf(ArithHelper.mul(firstValue, secondValue)); break; case '/': result = String.valueOf(ArithHelper.div(firstValue, secondValue)); break; } return result; } } class ArithHelper { // 默认除法运算精度 private static final int DEF_DIV_SCALE = 16; // 这个类不能实例化 private ArithHelper() { } /** * 提供精确的加法运算。 * * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(double v1, double v2) { java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1)); java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } public static double add(String v1, String v2) { java.math.BigDecimal b1 = new java.math.BigDecimal(v1); java.math.BigDecimal b2 = new java.math.BigDecimal(v2); return b1.add(b2).doubleValue(); } /** * 提供精确的减法运算。 * * @param v1 被减数 * @param v2 减数 * @return 两个参数的差 */ public static double sub(double v1, double v2) { java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1)); java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } public static double sub(String v1, String v2) { java.math.BigDecimal b1 = new java.math.BigDecimal(v1); java.math.BigDecimal b2 = new java.math.BigDecimal(v2); return b1.subtract(b2).doubleValue(); } /** * 提供精确的乘法运算。 * * @param v1 * 被乘数 * @param v2 * 乘数 * @return 两个参数的积 */ public static double mul(double v1, double v2) { java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1)); java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } public static double mul(String v1, String v2) { java.math.BigDecimal b1 = new java.math.BigDecimal(v1); java.math.BigDecimal b2 = new java.math.BigDecimal(v2); return b1.multiply(b2).doubleValue(); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。 * * @param v1 * 被除数 * @param v2 * 除数 * @return 两个参数的商 */ public static double div(double v1, double v2) { return div(v1, v2, DEF_DIV_SCALE); } public static double div(String v1, String v2) { java.math.BigDecimal b1 = new java.math.BigDecimal(v1); java.math.BigDecimal b2 = new java.math.BigDecimal(v2); return b1.divide(b2, DEF_DIV_SCALE, java.math.BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。 * * @param v1 被除数 * @param v2 除数 * @param scale 表示表示需要精确到小数点以后几位。 * @return 两个参数的商 */ public static double div(double v1, double v2, int scale) { if (scale < 0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1)); java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2)); return b1.divide(b2, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供精确的小数位四舍五入处理。 * * @param v 需要四舍五入的数字 * @param scale 小数点后保留几位 * @return 四舍五入后的结果 */ public static double round(double v, int scale) { if (scale < 0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } java.math.BigDecimal b = new java.math.BigDecimal(Double.toString(v)); java.math.BigDecimal one = new java.math.BigDecimal("1"); return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue(); } public static double round(String v, int scale) { if (scale < 0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } java.math.BigDecimal b = new java.math.BigDecimal(v); java.math.BigDecimal one = new java.math.BigDecimal("1"); return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue(); } }
总结:天天搞Android开发,注重的是技术的研究,至于算法这种东西,真的没有研究过,还有就是这上面的三道题目是面试题中常见的题目,我猜这家公司也是从网上找到和删选的三道题目,百度和google一下,到处都是,面试的时候只是在会议室里,只要你的移动网络好(所以赶快换4g的)的话,一个小时不到就能搞定,先不管其他的,先搞到面试的机会再说!还是最后要说的就是,现在不喜欢那些公司的面试题,大部分都是从网上找到的,还不如不笔试了,没有意义,而且讨厌在纸质上面写代码,很是蛋疼呀,第一字写的不好看,单词写的自己都懒得看,还有就是平时用电脑写代码搞惯了,因为方法名不记得了,Alt+/有提示的,写在纸上面就什么都忘了,不可能还去记那些方法,现在本人还在等通知,感觉自己不一定能搞到这个offer,其实我提喜欢这个公司和职位的,待遇不错,公司的办公环境也不错,期待呀!