SAP面试经历

地点:SAP金科路
时间:2015-03-24 14:00~17:30
部门:SME Anywhere团队
职位:Java Dev


笔试

时间:1小时
内容:C++、C#、JavaScript、Java、SQL、算法等
类型:英文题目
备注:Java相关及数据库和逻辑算法必做

Java基础知识

  1. HashMap与HashTable区别
    答:从线程安全、同步及速度三方面入手

    区别 HashMap HashTable
    键值对 可接受为null的键值(key)和值(value) 不可以
    是否同步 非synchronized synchronized,线程安全多个线程可共享
    效率 单线程性能较好 单线程下比前者慢
    迭代器 Iterator是fail-fast,当其他线程改变其结构时,会抛出ConcurrentModificationException Enumerator不是fail-fast
  2. 尽可能多地写出Runtime异常
    答:Java 的异常被分为两大类:Checked 异常和 Runtime 异常(运行时异常)。所有的 RuntimeException 类及其子类的实例被称为 Runtime 异常,不是 RuntimeException 类及其子类的异常实例则被称为 Checked 异常。

    • Runtime exceptions是runtime阶段碰到的异常,在编译的时候不需要检查(checked)
    • Checked exception 是在编译阶段的异常,并且强制检查

    ArithmeticException(除数为0的异常)
    BufferOverflowException(缓冲区上溢异常)
    BufferUnderflowException(缓冲区下溢异常)
    IndexOutOfBoundsException(出界异常)
    NullPointerException(空指针异常)
    EmptyStackException(空栈异常)
    IllegalArgumentException(不合法的参数异常)
    NegativeArraySizeException
    NoSuchElementException
    SystemException
    UndeclaredThrowableException

  3. 括号匹配,如何判断给定字符串是否合法。如”{}”和”{[()]}”为合法,而”{]”或”({[}])”都为非法。
    答:利用栈实现。遍历字符串,依次将左括号入栈,遇到右括号则弹出栈顶进行匹配,不匹配则非法;反之继续遍历,直到最后栈空,则合法。

    pyhton代码如下:

    
    # coding:utf-8
    
    brackets = ['{}', '[]', '()']
    bracket_left = ['{', '(', '[']
    bracket_right = ['}', ']', ')']
    
    def bracket_match(value):
        """
        括号匹配
        :param value:
        :return:
        """
        length = len(value)
        value_left = []
        for i in range(length):
            val = value[i]
            if val in bracket_left:
                value_left.append(val)
            elif val in bracket_right:
                if value_left:
                    val_left = value_left.pop()
                    val_bracket = val_left + val
                    if val_bracket in brackets:
                        continue
                    else:
                        print_result(value, False)
                        return
                else:
                    print_result(value, False)
                    return
    
        if value_left:
            print_result(value, False)
        else:
            print_result(value, True)
    
    def print_result(value, isvalid):
        """
        输出结果提示
        :param value:
        :param isvalid:
        :return:
        """
        if isvalid:
            print '{} is a vaild string'.format(value)
        else:
            print '{} is not a vaild string'.format(value)
    
    if __name__ == '__main__':
        while 1:
            param = raw_input('\nPlease input string:')
            bracket_match(param)

    java代码如下:

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.Stack;
    
    public class BracketsMatch {
        public static void main(String[] args) throws Exception {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("Please input string:");
            String input = br.readLine();
            if(isMatch(input)) {
                System.out.println(input + " is a vaild string!");
            } else {
                System.out.println(input + " is not a vaild string!");
            }
    }
    
        public static boolean isMatch(String input) {
            Stack st = new Stack();
            char temp;
            for (int i = 0; i < input.length(); i++) {
                temp = input.charAt(i);
                if (temp == '(') st.push(')');
                if (temp == '{') st.push('}');
                if (temp == '[') st.push(']');
                if (temp == ')' || temp == '}' || temp == ']') {
                    if (temp != st.pop()) return false;
                }
            }
            if (st.isEmpty() == true) return true;
            else return false;
        }
    } 

数据库

  1. 一张产品信息表Product(pname,pcolor,pcount),同一个产品名称不同颜色的生产数量比较,找出较大的那个,并求出其数量差。
    答:考察sql语句的自身连接查询。

    select P1.*, (P1.pcount - P2.pcount) as pdiff
    from Product P1, Product P2
    where P1.pname = P2.pname
        and P1.pcolor = 'yellow'
        and P2.pcolor = 'black'
        and P1.pcount > P2.pcount

逻辑算法

  1. 写出算法,如何判断链表有无环
    答:通过两个指针,分别从链表的头节点出发,一个每次向后移动一步,另一个移动两步,两个指针移动速度不一样,如果存在环,那么两个指针一定会在环里相遇。

    bool hasCircle(Node *head,Node *&circleNode)
    {
        Node *slow, *fast;
        slow = fast = head;
        while(fast != NULL && fast->next != NULL)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow) return true;
        }
        return false;
    }
  2. 估算出到2050年上海有多少名软件工程师
    答:个人认为此类问题没有正确答案,主要考察对具体问题的分析过程及思路。针对此题,我主要从下面几个方面切入:

    根据企业规模将软件公司划分等级
    根据今年上海注册软件公司估算目前工程师人数
    软件公司存活比例
    软件公司员工数新增比例

    这里可以假设目前上海全部软件工程师数目为n,按照企业规模将公司分为大型或跨国类(A),中小型软件类(B)以及国企央企银行类(C)。在中小型公司中,假定企业倒闭及新增数大致持平,那么显然员工流向无非就是倒闭公司到新兴企业,那么人数持平。A类公司则每年以20%的规模进行人数扩展,同时C类公司以每年10%规模扩展,那么可以得出2050年工程师人数:
    n + A(1 + 20%) + C(1 + 10%)


面试

时间:2个半小时
人次:4人
内容:结合简历及面试官个人经历
备注:略去项目介绍等内容

一面

  1. JQuery中map和when如何使用,试着写出来
    答:$.map()方法会在数组的每一个元素或对象上应用一个函数并将结果映射到一个新的数组中,同样也支持遍历对象。

    var map_array = { width: 10, height: 15, length: 20 };
    map_array = $.map( map_array, function( value, index ) {
      return value * 2;
    }); 

    $.when()提供一种方法来执行一个或多个对象的回调函数, Deferred(延迟)对象通常表示异步事件。具体参考jquery when的处理

  2. Spring好处都有些啥?解释下ioc和aop
    答:参考Spring的IOC原理、关于Spring的69个面试问答——终极列表以及Spring面试问题集锦

  3. 描述下堆排序算法
    答:堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。具体算法参考白话经典算法系列之七 堆与堆排序和精通八大排序算法系列:二、堆排序算法
    堆排序算法

  4. 解释下装饰器模式
    答:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。python中通过decorate关键字,将某一类公共操作放在一个方法中,其他操作执行前直接调用其即可,如下:

    def login(request): # 登录系统权限判断
        pass
    
    @login
    def dashboard(request):  # 首页展示处理
        pass
  5. Java中多线程如何实现?为什么需要多线程来处理?
    答:参考JAVA多线程和并发基础面试问答;在多线程程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态。多个线程共享堆内存(heap memory),因此创建多个线程去执行一些任务会比创建多个进程更好。参考Java 多线程编程以及java实现多线程的两种方法的比较

  6. Hibernate与iBatis的区别?iBatis的配置文件。
    答:区别参考iBATIS、Hibernate和JPA:哪一款最适合你以及Hibernate VS iBatis;配置文件参考iBatis配置文件

    iBatis Hibernate
    iBATIS is simpler. It comes in a much smaller package size. Hibernate generates SQL for you which means you don’t have to spend time on generating SQL.
    iBATIS is flexible. It offers faster development time. Hibernate is highly scalable. It provides a much more advanced cache.
    iBATIS uses SQL which could be database dependent. Hibernate uses HQL which is relatively independent of databases. It is easier to change db in Hibernate.
    iBatis maps the ResultSet from JDBC API to your POJO Objets, so you don’t have to care about table structures. Hibernate maps your Java POJO objects to the Database tables.
    It is quite easy to use stored procedure in iBATIS. Use of stored procedures is a little difficult in Hibernate.

二面

  1. 围绕简历等内容聊天

三面

  1. JQuery中都有什么类型?为什么都使用var?
    答:前者问题参考Javascript基本类型和重新介紹 JavaScript;因为Javascript为弱类型语言,故无需在声明时定义变量类型,系统会自动给其定义为objects对象,参考JavaScript 中对变量和函数声明的”提前(hoist)”和JavaScript 为什么要用 var 关键字申明变量

  2. JavaScript中的this作用域范围
    答:参考谈谈Javascript的this指针、深入javascript——作用域和闭包及Javascript的秘密花园

  3. Python中的self作用,与Java中this一样么?
    答:基本上来说,与this用法一致,都指代当前对象的地址,可以用来调用当前类中的属性和方法。但是,与多数时候可以省略的this不同,this用来提醒我们谁是形参谁是实参,而self不可以被省略,python中需要显示地指明对象。另外self就是一个参数,并非关键字,因而可以为任意名称。参考python中的类与self

  4. Python中的继承与Java中有何区别么?
    答:基本上是一致,但有略微区别,如下:

    • 在派生类中基类的构造方法(init())不会被自动调用,需要在其派生类的构造中亲自专门调用。

    • 在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。

    • Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(多继承话,只调用第最前面一个)

    原因猜测为:java需要先编译一下,编译成功后由java虚拟机执行,它在编译过程中先初始化父类,然后初始化子类,所以运行时先运行父类的构造函数,然后运行子类的构造方法。而python无需编译直接执行,所以不会运行父类的构造方法(当然除了在派生类中无法找到初始化方法)。

  5. JQuery中如何实现继承?解释下Prototype
    答:参考浅析JavaScript继承方式,JavaScript继承简单理解与实现以及jquery、prototype、mootools、YUI的继承的实现

  6. 解释下Node.js异步调度机制,为何要采用异步方式?根据什么规则进行调度?
    答:参考朴灵大大的Node.js的事件机制和初探Node.js的异步I/O实现;以及Node.js用来解决什么问题和我们为什么要用Node.js

  7. Linux如何查看具体进程端口号
    答:首先查看进程的进程号,再根据进程号查看进程端口

    ps -ef | grep 进程名
    netstat -nltp | grep 进程号
  8. 介绍下堆排序和快速排序算法
    答:堆排序查看一面中第三题。
    快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。参考快速排序算法和白话经典算法系列之六 快速排序 快速搞定
    快速排序

  9. 说说红黑树的特性
    答:红黑树是一种自平衡二叉查找树。它的统计性能要好于平衡二叉树(AVL树),因此,红黑树在很多地方都有应用。在C++ STL中,很多部分(目前包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持)。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除等操作。具体算法参考红黑树并没有我们想象的那么难(上)和红黑树(一)之 原理和算法详细介绍,另外可以了解相关AVL树的概念


四面

  1. Python中的metaclass知道么?如何使用?
    答:元类就是用来创建类的“东西”。你创建类就是为了创建类的实例对象,不是吗?但是我们已经学习到了Python中的类也是对象。好吧,元类就是用来创建这些类(对象)的,元类就是类的类。函数type实际上是一个元类。参考深刻理解Python中的元类(metaclass)和如何使用元类

  2. 写个层序遍历二叉树的算法
    答:通过队列来实现层序,依次将节点及其孩子入队,在出队操作时打印节点即可实现。

    def level_order_traverse(Node tree):
        node_list = []
        node_list.append(tree)
        print 'LevelTraverse result is: '
        while node_list:
            node = node_list.pop(0)
            print '{} ->'.format(node)
            if node.left:
                node_list.append(node.left)
            if node.right:
                node_list.append(node.right)
  3. 一个无穷大的整数,将其转换为中文大写字符。如103->壹佰零叁,80980876->捌仟零玖拾捌万捌佰柒拾陆。。。说说思路。
    答:此题目对于无穷大很不好处理,对于中文大写,由于叫法习惯、单位大小等问题,很难进行处理。当然考虑递归实现,按照兆进行不断划分。对于兆以下可以采用hard code方式匹配处理,这里想到一种思路,将所得数字每四个分为一组,进行处理,最后将字符串拼接起来。

你可能感兴趣的:(面试总结)