• 写在前面,几个月没怎么看过Java,昨天上午突然决定参加一下这个笔试,然后立马投了简历。晚上参加远程笔试,题目不算难,算是普通水平,算法题也没有难到不会写。但我还是把实现栈会写的写错最气人)的那题写错了,交完答案,重新看了一眼题,瞬间就骂自己sb,脑子当时不知道在想什么???这么简单的题,都给写错,怕是没机会参与面试了。不过也好,趁着最后一个月,多投几个简历,复习一下自己几个月没看的Java。最后,吐槽一下,纸上写代码简直是活受罪啊啊啊,强烈推荐算法题还是在线上编程比较好,另外就是我写的字太难看了(我是辣鸡,只会嘤嘤嘤…)。最后,不管结果如何,总结一下至关重要,另外也告诫自己,下一次遇到这种简单的题目就别写错了。在写错,自己就真是个sb了。

简答题

  • 写出你用过的linux命令,举例说明其中几个的具体用法。
  • mkdir、chomd、apt-get update、ifconfig、vim、cd、…(用法就不说了,不懂的Google)
  • 写出TCP的三次握手和四次握手的过程。
  • 三次握手:假设 A 为客户端,B 为服务器端。首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。A 向 B 发送连接请求报文,SYN=1,ACK=0,选择一个初始的序号 x。B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为 x+1,同时也选择一个初始的序号 y。A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为 y+1,序号为 x+1。B 收到 A 的确认后,连接建立。
  • 四次挥手:假设 A 为客户端,B 为服务器端。首先A 发送连接释放报文,FIN=1。B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据。当 B 不再需要连接时,发送连接释放报文,FIN=1。A 收到后发出确认,进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)后释放连接。B 收到 A 的确认后释放连接。
  • 将一个句子按单词反序。比如 “the sky is blue”,反序后变为 “blue is sky the”?
public static String reverse(String S) {
        String[] strs = S.trim().split(" ");
        StringBuilder sb = new StringBuilder();
        for (int i = strs.length - 1; i >= 0; i--) {
            sb.append(strs[i]);
            sb.append(" ");
        }
        return sb.toString().trim();
    }
  • 一张学生成绩表score,部分内容如下:
    name course grade
    张三 操作系统 67
    张三 数据结构 86
    李四 软件工程 89
    用一条SQL 语句查询出每门课都大于80 分的学生姓名。

这题这不会写,好久好久没写过SQL语句了,问题这就暴露出来了。看来自己需要好好复习一下SQL语句了。

答案:
select distinct name from score where name not in (select name from score where grade <= 80);
  • 接口和抽象类的区别是什么?
  • 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  • 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。(JDK 1.8 以后,接口里可以有静态方法和方法体了。)
  • 集合类用过哪些,分别列举出来,并指出它们各自使用了那些数据结构。
  • ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap、ConcurrentHashMap…
  • Spring的IOC和AOP是什么? Spring有哪些优点?谈谈你对spring的理解。
  • IOC:控制反转(Inversion of Control),即创建被调用者的实例不是由调用者完成,而是由 Spring 容器完成,并注入调用者。
  • AOP:面向切面,允许你定义方法拦截器切入点对代码进行干净地解耦,它实现了应该分离的功能,降低代码的耦合度。

编程题

  • 实现一个栈,包含栈的基本操作(pop、push、top、size)。
public class Stack {
    Queue<Integer> in;
    Queue<Integer> out;

    public Stack() {
        in = new LinkedList<>();
        out = new LinkedList<>();
    }

    public int pop() {
        return out.poll();
    }

    public void push(int x) {
        in.add(x);
        while (!out.isEmpty()) {
            in.add(out.poll());
        }
        Queue tmp = in;
        in = out;
        out = tmp;
    }

    public int top() {
        return out.peek();
    }

    public int size() {
        return (in.size()+out.size());
    }
}
class MyStack {
    Queue<Integer> queue;

    public MyStack() {
        queue = new LinkedList<Integer>();
    }
    
    public void push(int x) {
        int n = queue.size();
        queue.offer(x);
        for (int i = 0; i < n; i++) {
            queue.offer(queue.poll());
        }
    }
    
    public int pop() {
        return queue.poll();
    }
    
    public int top() {
        return queue.peek();
    }
    
    public int size() {
        return queue.size();
    }
}
// 用数组实现栈,缺点是数组的大小已经固定。因此栈的最大容量也已经确定。
class Stack {

    int[] stack;
    int i;
    public Stack() {
        stack = new int[1000];
        i = 0;
    }
    
    public void push(int x) {
        stack[i++] = x;
    }
    
    public int pop() {
        return stack[i--];
    }
    
    public int top() {
        return stack[i];
    }
    
    public int size() {
        return i+1;
    }
}
  • 给定一个无序数组arr,找到数组中未出现的最小正整数
例如arr = [-1, 2, -3, 4]。返回1
arr = [1, 2, 3, 4]。返回5

[要求]
时间复杂度尽可能的低。
public static int minInt(int[] arr) {
        int len = arr.length;
        for (int i = 0; i < len; i++){
            if (arr[i] > 0 && arr[i] < len) {
                int tmp = arr[arr[i]-1];
                arr[arr[i]-1] = arr[i];
                arr[i] = tmp;
            }
        }

        for (int i = 0;i < len; i++) {
            if (arr[i] != i+1) {
                return i+1;
            }
        }
        return len+1;
    }

你知道的越多,你不知道的越多。