美团点评2020校招系统开发方向笔试题

1/10 [问答题]

题目描述

如果线上某台虚机CPU Load过高,该如何快速排查原因?只介绍思路和涉及的Linux命令即可 。

回答

造成cpu load过高的原因: Full gc次数的增大、代码中存在Bug(例如死循环、正则的不恰当使用等)都有可能造成cpu load 增高。
1. jps -v:查看java进程号
2. top -Hp [java进程号]:查看当前进程下最耗费CPU的线程
3. printf "%x\n" [步骤2中的线程号]:得到线程的16进制表示
4. jstack [java进程号] | grep -A100 [步骤3的结果]:查看线程堆栈,定位代码行。

2/10[问答题]

题目描述

请简要描述MySQL数据库联合索引的命中规则,可举例说明。

回答

1) MySQL联合索引遵循最左前缀匹配规则,即从联合索引的最左列开始向右匹配,直到遇到匹配终止条件。例如联合索引(col1, col2, col3), where条件为col1=`a` AND col2=`b`可命中该联合索引的(col1,col2)前缀部分, where条件为col2=`b` AND col3=`c`不符合最左前缀匹配,不能命中该联合索引。
2) 匹配终止条件为范围操作符(>, <, between, like等)或函数等不能应用索引的情况。例如联合索引(col1, col2, col3), where条件为col1=`a` AND col2>1 AND col3=`c`, 在col2列上为范围查询,匹配即终止,只会匹配到col1,不能匹配到(col1, col2, col3).
3) where条件中的顺序不影响索引命中。例如联合索引(col1, col2, col3), where条件为col3=`c` AND col2=b AND col1=`a`, MySQL优化器会自行进行优化,可命中联合索引(col1, col2, col3).

3/10[问答题]

题目描述

什么是分布式事务,分布式事务产生的原因是什么?分布式事务的解决方案有哪些?分别有哪些优缺点?

回答

分布式事物:将一次大的操作分为很多小的操作,这些小的操作位于各自的服务器上,分布式事物需要保证这些小的操作要么全部成功,要么全部失败。
分布式事物产生的原因:1.为了解决不同数据库操作时数据不一致的问题。2.应用SOA话。
分布式事物的解决方案:
1.2PC:两阶段提交
优点:保证数据的强一致性,适合对数据要求高的强一致性领域。
缺点:实现复杂,牺牲了可用性,性能不高,不适合高并发,高性能的场景。
2.3PC:三阶段提交
优点:相对于二阶段,它减低了阻塞的范围,解决了协调者这参与者同时挂掉的问题,即等待超时后,协调者或参与者会中断事务,避免单点问题。
缺点:数据不一致性依然存在。
3.补偿事务(TCC)
优点:1)性能提升,2)数据最终一致, 3)可靠性更高
缺点:花费高

4/10[问答题]

题目描述

请描述https的请求过程。

回答

1) 客户端向服务器发起HTTPS请求,连接到服务器的443端口;
2) 服务器端有一个密钥对,即公钥(即数字证书)和私钥,是用来进行非对称加密使用的,服务器端保存着私钥,不能将其泄露,公钥可以发送给任何人;
3) 服务器将自己的公钥发送给客户端;
4) 客户端收到服务器端的公钥之后,检查其合法性,如果发现发现公钥有问题,那么HTTPS传输就无法继续,如果公钥合格,则客户端会生成一个客户端密钥,然后用服务器的公钥对客户端密钥进行非对称加密成密文,至此,HTTPS中的第一次HTTP请求结束;
5) 客户端发起HTTPS中的第二个HTTP请求,将加密之后的客户端密钥发送给服务器;
6) 服务器接收到客户端发来的密文之后,会用自己的私钥对其进行非对称解密,解密之后的明文就是客户端密钥,然后用客户端密钥对数据进行对称加密,这样数据就变成了密文;
7) 然后服务器将加密后的密文发送给客户端;
8) 客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,得到服务器发送的数据。这样HTTPS中的第二个HTTP请求结束,整个HTTPS传输完成。

5/10[问答题]

题目描述

什么是事务传播行为?你知道Spring事务中都有哪些传播类型吗?如何使用/指定传播类型?

1) 事务传播用于描述当一个由事务传播行为修饰的方法被嵌套入另外一个方法时,事务如何传播。常用于定义发生事务嵌套时,如何继续执行。
2) Spring 中共定义了7中事务传播类型,明细如下表, 需答出3~4种常见类型即可:
    a) PROPAGATION_REQUIRED: 当前没有事务时开启新事务,如果有则加入;
    b) PROPAGATION_REQUIRES_NEW: 强制开启新事务,挂起已有事务(如有);
    c) PROPAGATION_SUPPORTS: 当前有事务时加入, 没有则以非事务方式执行;
    d) PROPAGATION_NOT_SUPPORTED: 以非事务方式执行, 挂起当前事务(如有);
3) 可以在注解或者XML中指定传播类型, 如 “@Transactional(Propagation=xxx)

6/10[问答题]

题目描述

IO设计中Reactor 和 Proactor 区别。

1、 Reactor被动的等待指示事件的到来并作出反应,有一个等待的过程,做什么都要先放入到监听事件集合中等待handler可用时再进行操作,实现相对简单,对于耗时短的处理场景比较高效,但Reactor处理耗时长的操作会造成事件分发的阻塞,影响到后续事件的处理。
2、Proactor直接调用异步读写操作,调用完后立刻返回,实现了一个主动的事件分离和分发模型;这种设计允许多个任务并发的执行,从而提高吞吐量;并可执行耗时长的任务(各个任务间互不影响),Proactor性能更高,能够处理耗时长的并发场景,但Proactor实现逻辑复杂;依赖操作系统对异步的支持,目前实现了纯异步操作的操作系统少,实现优秀的如windows IOCP,但由于其windows系统用于服务器的局限性,目前应用范围较小;而Unix/Linux系统对纯异步的支持有限,应用事件驱动的主流还是通过select/epoll来实现。

7/10[编程题]大数加法

链接:www.nowcoder.com/questionTerminal/...

以字符串的形式读入两个数字,再以字符串的形式输出两个数字的和。

输入描述:

输入两行,表示两个数字a和b,-109 <= a , b <= 109  ,用双引号括起。

输出描述:

输出a+b的值,用双引号括起。

示例1

输入

"-26"
"100"

输出

"74"

回答

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        String num1 = in.nextLine().split("\"")[1];
        String num2 = in.nextLine().split("\"")[1];
        int sum = Integer.parseInt(num1)+Integer.parseInt(num2);
        System.out.println("\""+""+sum+"\"");
    }
}

8/10[编程题]回文子串

链接:www.nowcoder.com/questionTerminal/...

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串(回文串是一个正读和反读都一样的字符串)。

具有不同开始位置或结束位置的回文串,即使是由相同的字符组成,也会被计为是不同的子串。

输入描述:

输入仅包含一个字符串,长度不会超过 1000

输出描述:

输出仅包含一个非负整数, 代表输入字符串有多少个回文子串。

示例1

输入

abc

输出

3

示例2

输入

aaa

输出

6

回答

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String s = input.nextLine();
        int count = 0;
        StringBuilder sb=null;
        for (int i = 0; i < s.length(); i++) {
            for (int j = i; j < s.length(); j++) {
                sb = new StringBuilder(s.substring(i,j+1));
                if(sb.toString().equals(sb.reverse().toString())){
                    count++;
            }
            }
        }
        System.out.println(count);
    }
}

9/10[编程题]合并金币

链接:www.nowcoder.com/questionTerminal/...

有 N 堆金币排成一排,第 i 堆中有 C[i] 块金币。每次合并都会将相邻的两堆金币合并为一堆,成本为这两堆金币块数之和。经过N-1次合并,最终将所有金币合并为一堆。请找出将金币合并为一堆的最低成本。

其中,1 <= N <= 30,1 <= C[i] <= 100

输入描述:

第一行输入一个数字 N 表示有 N 堆金币第二行输入 N 个数字表示每堆金币的数量 C[i]

输出描述:

输出一个数字 S 表示最小的合并成一堆的成本

示例1

输入

4
3 2 4 1

输出

20

示例2

输入

30
10 20 30 40 50 60 70 80 90 100 99 89 79 69 59 49 39 29 19 9 2 12 22 32 42 52 62 72 82 92

输出

7307

回答

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] money = new int[n+1];
        int[] preSum = new int[n+1];
        for(int i = 1; i <= n; i++){
            money[i] = sc.nextInt();
            if(i == 1) {
                preSum[i] = money[i];
            }
            else {
                preSum[i] = preSum[i-1] + money[i];
            }
        }
        sc.close();

        int[][] dp = new int[n + 1][n + 1];
        for(int len = 2; len <= n; len++){
            for(int i = 1; i <= n - len + 1; i++){
                int j = i + len - 1;
                dp[i][j] = Integer.MAX_VALUE;
                int sum = preSum[j] - preSum[i - 1];
                for(int k = i; k < j; k++){
                    dp[i][j] = Math.min(dp[i][j],dp[i][k] + dp[k + 1][j] + sum);
                }
            }
        }
        System.out.println(dp[1][n]);
    }
}

10/10[编程题] 最小唯一前缀

链接:www.nowcoder.com/questionTerminal/...

给定一组个字符串,为每个字符串找出能够唯一识别该字符串的最小前缀。

输入描述:

第一行输入一个整数 n 表示字符串个数后面n行,每行一个字符串,一共n串互不相同的字符串。(2 <= n <= 100,字符串长度不超过100

输出描述:

输出n行,每行一个字符串,依次是每个字符串的最小可唯一识别前缀

示例1

输入

5
meituanapp
meituanwaimai
dianpingliren
dianpingjiehun
mt

输出

meituana
meituanw
dianpingl
dianpingj
mt

备注:

如果一个字符串S是另一个字符串T的前缀,则S的最小可识别前缀为S

回答

import java.util.Scanner;  
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        String[] strings = new String[N];
        for (int i = 0; i < N; i++)
            strings[i] = scanner.next();
        scanner.close();
        for (String s : strings)
            System.out.println(unique(s, strings));
    }
    //返回字符串s在字符串数组strings中最短唯一前缀
    private static String unique(String s, String[] strings) {
        //前缀初始为首字符
        String prefix = s.substring(0, 1);
        for (String single : strings) {
            //跳过字符串s本身
            if (single.equals(s)){
                continue;
            }
            //前缀被其他字符串包含,继续增加长度
            while (single.indexOf(prefix) == 0 && prefix.length() < s.length()) {
                prefix = s.substring(0, prefix.length()+1);   
            }
        }
        return prefix;
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!