【面经】数据研发一面-蚂蚁集团暑期实习

  蚂蚁集团的数字经济数据研发岗,没有问大数据相关的组件。个人感觉是偏向大数据的应用而非数仓开发。如果想传统数据开发建议投递蚂蚁集团的 CTO 线。这里感觉蚂蚁的面试是比较偏向于计算机基础的。

1.自我介绍

所有的面试几乎都是从这一步开始的,介绍一下自己的基本情况,包括目前是几年级,什么时候毕业,什么专业,导师研究什么方向,在学校里做了什么,为什么要报数据开发这个岗位。

2.学过什么专业课?

这个问题暗示下一步要对专业课的只是进行提问了,我们要准备好数据结构、计算机网络、操作系统、数据库等课程的八股文。

3.找第k大的数用什么算法?

回答:快排。

3.1 面试官:怎么做的?

回答:每次找一个元素,其值为 pivot, 将小于 pivot 的数移到 pivot 右边,大于 pivot 的数移动到左边,这样 pivot 就将数组分为两个部分,只需要将 k 与 pivot 所在的下标对比,缺点到左边继续查找还是右边继续查找。这里给出代码:

/* 数组中的第K个最大元素 */
class Solution {
    public int findKthLargest(int[] nums, int k) {
        int n = nums.length;
        quickSort(nums, 0, n - 1, k - 1);	// 从大到小排序,第k大元素的索引是k-1
        return nums[k - 1];
    }

    private void quickSort(int[] nums, int left, int right, int k) {
        int partition = randomPartition(nums, left, right);
        if (partition == k) {
            return;
        } else if (partition < k) {
            quickSort(nums, partition + 1, right, k);
        } else {
            quickSort(nums, left, partition - 1, k);
        }
    }

    private int randomPartition(int[] nums, int left, int right) {
        int pos = new Random().nextInt(right - left + 1) + left;
        swap(nums, left, pos);
        int pivot = nums[left];
        while (left < right) {
            while (left < right && nums[right] <= pivot) right--;
            nums[left] = nums[right];
            while (left < right && nums[left] >= pivot) left++;
            nums[right] = nums[left];
        }
        nums[left] = pivot;
        return left;
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}
面试官:快排找第k大数的时间复杂度是多少?

回答:平均时间复杂度 O(n)。

面试官:为什么是 O(n)?

回答:每次分割完,数组被划分成两个部分,只需要操作一边,而不需要操作另一边,理想或者平均情况下是 O(n)。这里简单说一下原理:

平均情况下:T(n) = T(n/2) + n;	第一次划分
		= T(n/4) + n/2 + n;		第二次划分  
		= T(n/8) + n/4 +n/2 +n;	第三次划分
		= ...
		= T(n/n) + 2 + 4 + ... + n;  第m次划分

等比数列求和公式:a1*(1-q^k) / (1-q), 这里 q=2
数量的第k项是n,那么2^(k-1)=n,那么时间复杂度:
(1-2^k)/(1-2) = 2^k-1 = 2 * 2^(k-1) - 1 = 2*n-1
即时间复杂度O(2*n-1)=O(n)
面试官:最坏时间复杂度呢?时间复杂度稳定吗?

回答:O(n^2),不稳定,如果每次找到的数都在两端,不能把数组分成两部分。最终会将所有数据都排好序。

面试官:有没有时间复杂度稳定的算法?

回答:堆排序。建立一个大小为 k 的小顶堆,将数组中的数逐个入堆,规则是比堆顶小的元素肯定不是第 k 大,因为是小顶堆,堆顶是最小的,而堆顶的序号至少是 k(因为堆的大小为 k,里面的数都比 k 大)。如果新的元素比堆顶元素大,那么将堆顶元素出堆,新的元素加入堆中。时间复杂度为:O*(*nlogk) 。这里给出代码:

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int len = nums.length;
        // 使用一个含有 k 个元素的最小堆
        // PriorityQueue 底层是动态数组,为了防止数组扩容产生消耗,可以先指定数组的长度
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, new Comparator<Integer>(){
            @Override
            public int compare(Integer a, Integer b) {
                return a.compareTo(b);
            }
        });
        for (int i = 0; i < k; i++) {
            minHeap.offer(nums[i]);
        }
        for (int i = k; i < len; i++) {
            // 看一眼,不拿出,因为有可能没有必要替换
            Integer topElement = minHeap.peek();
            // 只要当前遍历的元素比堆顶元素大,堆顶弹出,遍历的元素进去
            if (nums[i] > topElement) {
                minHeap.poll();
                minHeap.offer(nums[i]);
            }
        }
        return minHeap.peek();
    }
}

其实还有最坏时间复杂度为 O(n) 的算法,《算法导论》9.3章给出了一个最差情况也为线性O(n)的算法。

4.MySQL 的索引用什么数据结构?

B+ 树。

4.1 面试官:讲一下 B 树和 B+ 树?

回答:B 树 指的是 Balance Tree,也就是平衡树。平衡树是一颗查找树,并且所有叶子节点位于同一层。

B+ 树 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具有 B Tree 的平衡性,并且通过顺序访问指针来提高区间查询的性能。

4.2 面试官:为什么B+ 树更好?提示:在访问磁盘方面

回答:

  • B 树的关键字、记录和索引是放在一起的;B+ 树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。
  • 在B 树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。从这个角度看B 树的性能好像要比B+ 树好,而在实际应用中却是B+ 树的性能要好些。因为B+ 树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比B 树多,树高比B 树小,这样带来的好处是减少磁盘访问次数。尽管B+ 树找到一个记录所需的比较次数要比B 树多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中B+ 树的性能可能还会好些,而且B+ 树的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等),这也是很多数据库和文件系统使用B+ 树的缘故。

总结一下就是:

  • B+ 树的磁盘读写代价更低 :B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说 IO 读写次数也就降低了。
  • B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
5.浏览一个网站怎么加密?

HTTPS(SSL/TLS)的加密机制。

  • 对称加密:只有一个密钥,它可以加密一段信息,也可以对加密后的信息进行解密。缺点:无法安全将密钥传输给对方,同时不被别人知道。如果由服务器生成一个密钥并传输给浏览器,那在这个传输过程中密钥可能被别人劫持。

  • 非对称加密:一把叫做公钥、一把叫私钥,用公钥加密的内容必须用私钥才能解开,同样,私钥加密的内容只有公钥能解开。服务器先把公钥以明文方式传输给浏览器,之后浏览器向服务器传数据前都先用这个公钥加密好再传,这条数据的安全似乎可以保障了,因为只有服务器有相应的私钥能解开公钥加密的数据。

  • 非对称加密+对称加密:非对称加密耗时,可以采用如下方法:

    1. 某网站拥有用于非对称加密的公钥 A、私钥 A’。
    2. 浏览器向网站服务器请求,服务器把公钥 A 明文给传输浏览器。
    3. 浏览器随机生成一个用于对称加密的密钥 X,用公钥 A 加密后传给服务器。
    4. 服务器拿到后用私钥 A’ 解密得到密钥 X。
    5. 这样双方就都拥有密钥 X 了,且别人无法知道它。之后双方所有数据都通过密钥 X 加密解密即可。
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值