当前位置 博文首页 > 我有失忆症:??万字阿里技术岗笔面试题+参考答案,自信的可以来

    我有失忆症:??万字阿里技术岗笔面试题+参考答案,自信的可以来

    作者:[db:作者] 时间:2021-08-14 15:12

    前些日子在网上偶然间看到了一波阿里的技术笔面试题,自己自信地尝试做了一波,但结果很可惜,在不上网搜参考的情况下,20道题我只做出来8个…真尴尬。

    在这里插入图片描述

    题目水平高低起伏,这里我先把所有题目给大家看一遍,大多数题目后面都有参考答案,个别的确实没找着答案,大家可以现在这里看一遍题目去思考一下你自己的答案,看你在不看答案的情况下能做出几个来。

    一、题目预览

    1.如何实现两金额数据相加(最多小数点两位)?
    .
    2.有一批气象观测站,现需要获取这些站点的观测数据,并存储到 Hive 中。但是气象局只提供了 api 查询,每次只能查询单个观测点。那么如果能够方便快速地获取到所有的观测点的数据?
    .
    3.请计算XILINX公司VU9P芯片的算力相当于多少TOPS,给出计算过程与公式。
    .
    4.给定一个整数数组和一个整数,返回两个数组的索引,这两个索引指向的数字的加和等于指定的整数。需要最优的算法,分析算法的空间和时间复杂度。
    .
    5.MySQL 的数据如何恢复到任意时间点?
    .
    6.给定一个二叉搜索树(BST),找到树中第 K 小的节点。
    .
    7.一颗现代处理器,每秒大概可以执行多少条简单的MOV指令,有哪些主要的影响因素?
    .
    8. 在云计算大数据处理场景中,每天运行着成千上万的任务,每个任务都要进行 IO 读写。存储系统为了更好的服务,经常会保证高优先级的任务优先执行。当多个作业或用户访问存储系统时,如何保证优先级和公平性?
    .
    9.如何实现一个高效的单向链表逆序输出?
    .
    10. 你理解常见如阿里,和友商大数据平台的技术体系差异以及发展趋势和技术瓶颈,在存储和计算两个方面进行概述。
    .
    11.如果让你来设计一个支持数据库、NOSQL 和大数据之间数据实时流动的数据流及处理的系统,你会考虑哪些问题?如何设计?
    .
    12.假如给你一个新产品,你将从哪些方面来保障它的质量?
    .
    13.已知 sqrt (2)约等于 1.414,要求不用数学库,求 sqrt (2)精确到小数点后 10 位。
    .
    14.LRU 缓存机制,设计和实现一个 LRU(最近最少使用)缓存数据结构,使它应该支持一下操作:get 和 put。 get(key) - 如果 key 存在于缓存中,则获取 key 的 value(总是正数),否则返回 -1。 put(key,value) - 如果 key 不存在,请设置或插入 value。当缓存达到其容量时,它应该在插入新项目之前使最近最少使用的项目作废。
    .
    15.给定一个链表,删除链表的倒数第 N 个节点,并且返回链表的头结点。
    .
    16.输入 ping IP 后敲回车,发包前会发生什么?
    .
    17.请解释下为什么鹿晗发布恋情的时候,微博系统会崩溃,如何解决?
    .
    18. 关于并行计算的一些基础开放问题。
    .
    19.请评估一下程序的执行结果?
    .
    20.现有一批邮件需要发送给订阅顾客,且有一个集群(集群的节点数不定,会动态扩容缩容)来负责具体的邮件发送任务,如何让系统尽快地完成发送?请详述技术方案!

    阿里的笔面试题和答案我已整理成文档,如果你文章看不习惯文章的话,可以找我要文档去看的。


    二、参考答案

    以下只是网上的一些大神以及小哥自己做出的一些参考答案,并非出自阿里内部的答案,大家没有头绪的情况下可以参考参考。

    1.如何实现两金额数据相加(最多小数点两位)?

    出题人:阿里巴巴出题专家:御术/蚂蚁金服数据可视化高级技术专家

    参考答案

    其实问题并不难,就是考察候选人对 JavaScript 数据运算上的认知以及考虑问题的缜密程度,有很多坑,可以用在笔试题,如果用在面试,回答过程中还可以随机加入有很多计算机基础的延伸。

    回到这个问题,由于直接浮点相与加会失精,所以要转整数;(可以插入问遇到过吗?是否可以举个例子?)。

    转整数是第一个坑,虽然只有两位可以通过乘以100转整数,但由于乘以一百和除以一百都会出现浮点数的运算,所以也会失精,还是要通过字符串来转;(可以插入问字符串转整数有几种方式?)字符串转整是第二个坑,因为最后要对齐计算,如果没考虑周全先toFixed(2),对于只有一位小数点数据进入计算就会错误;转整数后的计算是个加分点,很多同学往往就是直接算了,如果可以考虑大数计算的场景,恭喜同学进入隐藏关卡,这就会涉及如何有效循环、遍历、算法复杂度的问题。


    2.有一批气象观测站,现需要获取这些站点的观测数据,并存储到 Hive 中。但是气象局只提供了 api 查询,每次只能查询单个观测点。那么如果能够方便快速地获取到所有的观测点的数据?

    出题人:阿里巴巴出题专家:江岚/阿里巴巴数据技术高级技术专家

    参考答案

    A. 通过 shell 或 python 等调用 api,结果先暂存本地,最后将本地文件上传到 Hive 中。

    B. 通过 datax 的 httpReader 和 hdfsWriter 插件,从而获取所需的数据。

    C. 比较理想的回答,是在计算引擎的 UDF 中调用查询 api,执行UDF 的查询结果存储到对应的表中。一方面,不需要同步任务的导出导入;另一方面,计算引擎的分布式框架天生提供了分布式、容错、并发等特性。


    3.请计算XILINX公司VU9P芯片的算力相当于多少TOPS,给出计算过程与公式。

    出题人: 阿里巴巴出题专家:隐达/阿里云异构计算资深专家

    参考答案:基于不同的算法,这个值在十几到几百之间。但是,如果只是单纯比算力,FPGA和ASIC、GPU相比并无太大优势,甚至大多时候有较大劣势。FPGA的优势在于高度的灵活性和算法的针对性。

    在这里插入图片描述


    4.给定一个整数数组和一个整数,返回两个数组的索引,这两个索引指向的数字的加和等于指定的整数。需要最优的算法,分析算法的空间和时间复杂度

    参考答案:

        Ha
        public int[] twoSum(int[] nums, int target) {
        if(nums==null || nums.length<2)
            return new int[]{0,0};
     
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for(int i=0; i<nums.length; i++){
            if(map.containsKey(nums[i])){
                return new int[]{map.get(nums[i]), i};
            }else{
                map.put(target-nums[i], i);
            }
        }
     
        return new int[]{0,0};
    }
    

    分析:空间复杂度和时间复杂度均为 O(n)

    在这里插入图片描述


    5.MySQL 的数据如何恢复到任意时间点?

    出题人:阿里巴巴出题专家:近秋/阿里云数据库产品技术部技术专家参考答案

    参考答案:恢复到任意时间点以定时的做全量备份,以及备份增量的 binlog 日志为前提。恢复到任意时间点首先将全量备份恢复之后,再此基础上回放增加的 binlog 直至指定的时间点。


    6.给定一个二叉搜索树(BST),找到树中第 K 小的节点。

    出题人:阿里巴巴出题专家:文景/阿里云 CDN 资深技术专家

    参考答案:

    • 考察点
      基础数据结构的理解和编码能力
      递归使用
    • 示例
           5
          / \
         3   6
        / \
       2   4
      /
     1
    

    说明:保证输入的 K 满足 1<=K<=(节点数目)

    解法1

    树相关的题目,第一眼就想到递归求解,左右子树分别遍历。联想到二叉搜索树的性质,root 大于左子树,小于右子树,如果左子树的节点数目等于 K-1,那么 root 就是结果,否则如果左子树节点数目小于 K-1,那么结果必然在右子树,否则就在左子树。因此在搜索的时候同时返回节点数目,跟 K 做对比,就能得出结果了。

    /**
     * Definition for a binary tree node.
     **/
    
    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) { val = x; }
    }
    
    class Solution {
        private class ResultType {
        
            boolean found;  // 是否找到
            
            int val;  // 节点数目
            ResultType(boolean found, int val) {
                this.found = found;
                this.val = val;
            }
        }
    
        public int kthSmallest(TreeNode root, int k) {
            return kthSmallestHelper(root, k).val;
        }
    
        private ResultType kthSmallestHelper(TreeNode root, int k) {
            if (root == null) {
                return new ResultType(false, 0);
            }
    
            ResultType left = kthSmallestHelper(root.left, k);
    
            // 左子树找到,直接返回
            if (left.found) {
                return new ResultType(true, left.val);
            }
    
            // 左子树的节点数目 = K-1,结果为 root 的值
            if (k - left.val == 1) {
                return new ResultType(true, root.val);
            }
    
            // 右子树寻找
            ResultType right = kthSmallestHelper(root.right, k - left.val - 1);
            if (right.found) {
                return new ResultType(true, right.val);
            }
    
            // 没找到,返回节点总数
            return new ResultType(false, left.val + 1 + right.val);
        }
    }
    
    
    

    解法2:

    基于二叉搜索树的特性,在中序遍历的结果中,第k个元素就是本题的解。 最差的情况是k节点是bst的最右叶子节点,不过每个节点的遍历次数最多是1次。 遍历并不是需要全部做完,使用计数的方式,找到第k个元素就可以退出。 下面是go的一个简单实现。

    // BST is binary search tree
    type BST struct {
    	key, value  int
    	left, right *BST
    }
    
    func (bst *BST) setLeft(b *BST) {
    	bst.left = b
    }
    
    func (bst *BST) setRight(b *BST) {
    	bst.right = b
    }
    
    // count 查找bst第k个节点的值,未找到就返回0
    func count(bst *BST, k int) int {
    	if k < 1 {
    		return 0
    	}
    
    	c := 0
    	ok, value := countRecursive(bst, &c, k)
    
    	if ok {
    		return value
    	}
    
    	return 0
    }
    
    // countRecurisive 对bst使用中序遍历
    // 用计数方式控制退出遍历,参数c就是已遍历节点数
    func countRecursive(bst *BST, c *int, k int) (bool, int) {
    	if bst.left != nil {
    		ok, value := countRecursive(bst.left, c, k)
    		if ok {
    			return ok, value
    		}
    	}
    
    	if *c == k-1 {
    		return true, bst.value
    	}
    
    	*c++
    
    	if bst.right != nil {
    		ok, value := countRecursive(bst.right, c, k)
    		if ok {
    			return ok, value
    		}
    	}
    
    	return false, 0
    }
    
    // 下面是测试代码,覆盖了退化的情况和普通bst
    
    func createBST1() *BST {
    	b1 := &BST{key: 1, value: 10}
    	b2 := &BST{key: 2, value: 20}
    	b3 := &BST{key: 3, value: 30}
    	b4 := &BST{key: 4, value: 40}
    	b5 := &BST{key: 5, value: 50}
    	b6 := &BST{key: 6, value: 60}
    	b7 := &BST{key: 7, value: 70}
    	b8 := &BST{key: 8, value: