美文网首页
快手java面经

快手java面经

作者: 一个IT人 | 来源:发表于2020-09-05 14:14 被阅读0次

    写在前面

    快手面试还算是简单一些,人性化一些,更多的是考虑技术选型,比如多种MQ的优缺点,未来如何做技术选型等。

    一面

        快手的第一面聊的时间久些,历时1小时45分钟,主要是把我工作多年的4个大项目都详细的聊一下

    项目

    所问的项目,基本套路就是:为了解决什么业务做了什么样的架构设计,其中遇到了什么难点和亮点。你可以围绕高并发、高性能、稳定性、可靠性、一致性等等描述一下你的亮点...

    技术

    1、技术选型    

            double与grpc的对比

    这里回答的不太好,没了解过grpc,回答的double与springcloud区别

    redis与memcached

    从存储结构、持久化等对比,重点讲的是redis的知识

    rocketmq与kafka

    这里回答的也不好,对比的少,介绍rocket的较多,rocket的发送端可靠性、服务端可靠性、消费端可靠性,注册中心、事务等

     2、基础知识

    Executors 与 ThreadPoolExecutor的选择,为什么选择后者

    1、可读性强,便于开发与合作

    2、重点是线程的数量和阻塞队列可控,并不会轻易导致线程无限分配抢占所有cpu和内存泄漏等问题


    redis的list结构压缩表和跳表

    算法

    问题

    数组里引用数组,死循环后break

    输入

    A : a,b,c,B

    B: C, c

    C: A,

    输出

    A: a,b,c,c

    B: a,b,c,c

    C:  a , b, c,c

    isGroup()

    Map<String, Set<String>>

    public void convert(Map<String, Set<String>> data) {

    }

    我的解题算法,感觉写的并不是很好

    public static void main(String[] args) {

        Map<String, Set<String>> va = new HashMap();

        Set<String> A = new HashSet<>();

        A.add("a");

        A.add("b");

        A.add("c");

        A.add("B");

        va.put("A", A);

        Set<String> B = new HashSet<>();

        B.add("C");

        B.add("c");

        va.put("B", B);

        Set<String> C = new HashSet<>();

        C.add("A");

        va.put("C", C);

        va.forEach((s, values) ->{

            Map<String, List<String>> temp = new HashMap();

            getValue2(va, temp, s, values);

            System.out.println(s + ":" + JSONObject.toJSONString(temp.get(s)));

        });

    }

    private static void getValue2(Map<String, Set<String>> va, Map<String, List<String>> temp, String key,

                                  Set<String> value) {

        if (temp.containsKey(key)) {

            return;

        }

        temp.put(key, null);

        List<String> list = new ArrayList<>();

        value.forEach(s ->{

            if (!s.equals(s.toLowerCase())) {// 大写的字母的时候

                if (temp.get(s) == null) {

                    getValue2(va, temp, s, va.get(s));

                }

                if (temp.get(s) != null) {

                    list.addAll(temp.get(s));

                }

            } else {//小写的字母直接加减

                list.add(s);

            }

        });

        temp.put(key, list);

    }

    二面

    二面就没问业务,上来就是技术的问题,历时1:30分钟

    技术

    1、mq,遇到过什么问题,怎么解决的?offset对于失败的消息如何记录

    2、redis 内存击穿,如何存储空值以节省空间

        1.Redis 集合(Set)

        2.位图存储

        3.布隆过滤器

    3、set的结构,在使用的时候有什么问题

    4、JVM:OOM的问题排查,CMS收集器

    设计题

    请设计一个服务上云的方案

        需要考虑3点1.web  2.redis  3.mysql

    数据迁移的过程中,考虑好一些碰撞,和存量数据和增量数据的处理。

    算法

    表达式计算,数字的加减乘除

    int calculate(String exp)

            正整数,+ - * /,

            int calculate(String exp)

            exp = "(3-2)*12+3*3*2"

            Positive integer, + - *,

    这道题其实压栈的思想

    思路:

    1. 如果碰到数字, 则把数字入栈

    2. 如果碰到空格, 则继续下一步

    3. 如果碰到 '+' '-' '*' '/', 则查找下一个数字num

        A.如果是'+', 下一个数字num直接入栈

        B.如果是'-',-num入栈

        C.如果是'*', num = stack.pop() * num, 入栈

        D.如果是'/', num = stack.pop() / num, 入栈

    4. 最后,把栈里的数相加就是结果

    public int calculate(String s) {

        char[] cs = s.trim().toCharArray();

        Stack<Integer> st = new Stack();

        int ans= 0, i= 0;

        while (i< cs.length) {

            if (cs[i] == ' ') {

                i++;

                continue;

            }

            char tmp = cs[i];

            if (tmp == '*' || tmp == '/' || tmp == '+' || tmp == '-') {

                i++;

                while (i< cs.length && cs[i] == ' ') { i++; }

    }

            int num= 0;

            while (i< cs.length && Character.isDigit(cs[i])) {

                num= num* 10 + cs[i] - '0';

                i++;

            }

            switch (tmp) {

                case '-':

                    num= -num;

                    break;

                case '*':

                    num= st.pop() * num;

                    break;

                case '/':

                    num= st.pop() / num;

                    break;

                default:

                    break;

            }

            st.push(num);

        }

        while (!st.isEmpty()) { ans+= st.pop(); }

        return ans;

    }

    三面


    技术题


    1、redis集群主从方式,主机down机的处理,与memcache的区别,key的失效策略

    2、rocketmq与kafaka的区别

    3、nago协议和inode

    设计与算法题

    1、767的阶乘后边有多少个0

    可以➗5的,25里有2个5

    static int factorial(int num) {

        int result= 0;

        for (int i= 1; i<= num; i++) {

            /*

    //方法1

    if (i % 5 == 0) {

    result++;

    int temp = i / 5;

    while (temp % 5 == 0) {

    result++;

    temp = temp / 5;

    }

    }*/

            if (i% 5 == 0) {

                int temp= i;

                do {

                    result++;

                    temp= temp/ 5;

                } while (temp% 5 == 0);

            }

    }

        return result;

    }

    public static void main(String[] args) {

        System.out.println(factorial(26));

    }

    2、大文件1G ,每个词条16字节,1M内存,求出词频最高的100条数据

        由于内存的限制,所以不能同时将1G的文件进行分析计算,可以使用分而治之的思想,将文件分为多个,可以分为某一个只有1M的,这样将小文件的计算就不会出现超出内存的问题了。

        分隔的方法就是将每一个单词进行hash后,hash%5000这样将单词分割到5000个小文件里,1G/5000大约一个文件200k,重复单词一定被分割到同一个文件中。

        由于没一项是一个单词,可以采用字典树Trie进行统计/hashmap,统计每个文件中出现的次以及频率。字典树的时间复杂度为单词最长的数值+遍历一遍n*O(k),hash为遍历一遍+产生hash+冲突解决

        对每一个小文件取出其中频率最大的前100个单词,然后进行合并,或者直接进行归并排序/堆排序,nlog(k)

    问答环节

        基本上是我来问了,问一问部门的业务,用到什么的技术,有什么苦难和瓶颈?

    HR

    一些基本问题,工作表现,个人的优缺点,遇到过什么问题,怎么解决的

    相关文章

      网友评论

          本文标题:快手java面经

          本文链接:https://www.haomeiwen.com/subject/azltektx.html