阿里巴巴算法工程师实习笔试&面试

三面凉了😩

素质测评

阿里素质测评总计50分钟左右,共四部分:文字理解、数学、图形推断、性格测试。前三部分每部分10题左右,每部分10分钟左右。性格测试我记得有98个题目,不计时,大概需要30分钟。

文字理解

给一段话,做阅读理解。

数学

读条形图、拆线图、饼图等统计图,然后计算给的题。

图形推断

找规律。
前三个难度:图形推断 > 文字理解 > 数学

性格测试

每道题给你三个选项,从中选出最适合你和最不适合你的词条。词条大多与工作方式、性格、领导力有关,比如创新、听取别人意见、意志力、负责人、信任他人、社交等等关键词。有些词条会反复出现,这是为了让最后的测试结果更科学,因为你可能同一个词条在不同组中有不一样的权重,或者我们自己都不确定到底哪个更合适,多次测取能输出一个更稳定综合的结果。因为没有计时,所以大可安下心来作答。
我觉得这里没必要找诀窍,如实作答就好。毕竟,找工作是双向选择,要是找到给你脾性不和的,身心受折磨的是你自己;找到情投意合的,才能和同事们一起开天辟地啊!

但总觉得选得前后不一也不好,太极端也不好。

笔试

1h,2道题,ACM赛制。
用的是牛客的评测系统,网页上调用摄像头和录屏,同时手机开小程序(但不用架在后面录像,就在一边摆着证明你没有看手机就行)。我感觉没用,因为完全可以在旁边再开另一个电脑。

第一题

题意

给一个数组,问把至少一半的数改为平方数最少多少步。
改法:+1或-1.

思路

分别统计每一个数需要的次数,排序再找前一半的数相加得到答案。
bool is_square()写多了,不用管。

代码

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

const int maxn = 2e5 + 5;

bool is_square(int x) {
    int sqrt_x = sqrt(x);
    if (sqrt_x * sqrt_x == x)
        return true;
    return false;
}

int need_quan(int x) {
    int sqrt_x = sqrt(x);
    return min(x - sqrt_x * sqrt_x, (sqrt_x + 1) * (sqrt_x + 1) - x);
}

int main(int argc, const char * argv[])
{
    int n, a[maxn], b[maxn], ans = 0;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        b[i] = need_quan(a[i]);
    }
    sort(b, b + n);
    int half = (n & 1) ? n / 2 + 1 : n / 2;
    for (int i = 0; i < half; i++) {
        ans += b[i];
    }
    cout << ans << endl;
    return 0;
}

很简单,10min以内过了。接下来的时间都在第二题里自闭。

第二题

题意

给两个数组a[n]、b[n],选3组,i<j<k,要求a[i]<=a[j]<=a[k],问b[i]+b[j]+b[k]最小值。

样例

输入

8
9 8 6 7 7 2 9 2
9 1 10 8 6 4 8 6

输出

24

思路

很迷惑为什么不是选4、5、7组,得到答案22.
牛客有个问问题的小窗,问完得到答复是题没问题。
于是回去读题,就是想不通。
交了个O(n3)的代码,但居然没T而是WA了,大概过了26%的点。

代码

#include <iostream>
using namespace std;

const int maxn = 3005;

int main(int argc, const char * argv[])
{
    int n, a[maxn], b[maxn], ans = 3e5 + 5;
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    for (int i = 0; i < n; i++)
        cin >> b[i];
    if (n < 3) {
        cout << -1 << endl;
        return 0;
    }
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (a[i] > a[j])
                break;
            for (int k = j + 1; k < n; k++) {
                if (a[i] > a[k] || a[j] > a[k])
                    continue;
                ans = min(ans, b[i] + b[j] + b[k]);
                //cout<<b[i]<<' '<<b[j]<<' '<<b[k]<<endl;
            }
        }
    }
    if (ans == 3e5 + 5)
        ans = -1;
    cout << ans << endl;
    return 0;
}

真的快崩溃了,又看了40min题没看出来哪里理解的不对。

一面

形式:电话。
比约定时间迟了40min才给我打电话,之前回播也没有人类回答,等得很方,怕不是被放鸽子。吸取教训,之后约面试之前一定问到个能回复的联系方式。

面试

自我介绍

略。
问了竞赛相关,大概讲了下ACM-ICPC的比赛规则和具体考的东西。

项目

由于还是本科生没做过什么大的项目所以介绍了操作系统数据库做的大作业。主要说了数据库那个用到的东西和实现功能:图书管理系统、用C++和mysql,做了后端数据库和前端的客户端。
Q:是否有机器学习的项目?
A:无。
Q:一共写的代码量多少?除去竞赛。
A:???真没仔细想过。工程的话一个文件大概100-300行,一个工程10-20个文件,所以写过的能有1万行吧。。。?

算法

Q:给一个数组,里面有的数出现偶数次,有个出现奇数次,怎么找?
A:开个hashmap计数统计。更高效的办法:求异或和,偶数异或都是0,剩下的答案是那个奇数次的。

闲聊

城市

Q:现在学校在哪?
A:西安。
Q:有杭州和北京,相去哪里?
A:杭州,更喜欢南方城市。
Q:哪里人?
A:东北QAQ

Q:喜欢看什么书?
A:计算机相关的,算法方面看过刘汝佳还有个日本人写的竞赛书,软件工程看过《人月神话》。娱乐方面,中学看过一些推荐必读书目、名著啥的,流行小说也看,大学看的少了。

学习与工作

Q:上过什么课?
A:必修的有操作系统、网络、数据库等,选修过密码学、网络攻防等等我觉得有意思的课。
Q:学过的东西对工作什么帮助?对算法岗位的理解?(具体问的啥记不住了,差不多是这)
A:从大量数据中快速检索想要的数据,或者修改数据?
Q:和你之前说的不太一致。主要是在做智能算法、去掉数据中的噪声、报警系统这些。
A:虽然没有做过相关的项目但是很感兴趣,想要了解。

反问

Q:你说的这个岗做的和我理解可能不大一致,那是否有其他哪个和我所学更贴近?
A:不太了解,要问问其他人。
Q:(放鸽子PTSD)下一轮面试怎样联系?是邮箱发链接还是电话QQ微信?
A:留了电话让加微信。下个面试官人在美国,所以只能约上午面。

总结

就尬聊,他也经常不知道问啥卡了很久。

二面

形式:开始要视频,但是他那边听不见声音就换成了电话。
破费了,从美国打过来打了1个小时。

面试

介绍工作

这是我遇到的第一个上来先给我介绍工作内容的面试官!
大致是他们是做云监控的,主要干的活是数据收集、聚合、开发算法等等。

自我介绍


被表扬了成绩好(啊这?我成绩就中等诶)和竞赛参加很多。

算法

Q:介绍一个你觉得比较有代表性的竞赛?
A:ACM-ICPC
Q:介绍一种用过的算法?怎么分析?解决什么问题?
A:回想了给腾讯讲的DP,于是又开始说DP和背包问题。但由于记得不算太清被打断了。
Q:学过与算法相关的课?
A:算法设计与分析,也是讲和上面竞赛差不多的内容,但是稍微简单一点。
Q:有没有大的项目?
A:算法课还就没做过,其他课做过。(又说了下GitHub上挂着的那两个CPU和数据库)
Q:机器学习?
A:没学过,了解不多。准备这学期或者下学期选一些相关的选修课。

语言

Q:用什么语言?
A:主要C/C++,偶尔写Java。
Q:Python?
A:大一在社团时候弄过,后来不大用就没用过。
Q:常写代码吗?刷题情况?
A:大学一直在做竞赛所以一直在练。

笔试

形式:给了一个链接,在线写代码,无评测环境。他一边出题我一边写。

代码

两点间距离

# calculate the Euclidean distance between two vectors (exclude the last elem)
# input: [1, 2, 0], [2, 8, 0], output (sqrt((1-2)**2 +(2-8)**2)
struct point {
  int x, y;
  string label;
} a, b;

double euc(point a, point b) {
  return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

求距test_row最近的num_neighbors个点

# Locate the most similar neighbors
# def get_neighbors(train, test_row, num_neighbors):
bool cmp(point a, point b, point test_row) {
  return euc(a, test_row) < euc(b, test_row);
}

vector<point> get_neighbors(vector<point> train, point test_row, int num_neighbors) {
  sort(train.begin(), train.end(), cmp);
  vector<point> res;
  for (int i = 0; i < num_neighbors && i < train.size(); i++)
    res.push_back(train[i]);
  return res;
}

最近的点中出现最多的lable

# Make a classification prediction with neighbors
# def predict_classification(train, test_row, num_neighbors):
string predict_classification(vector<point> train, point test_row, int num_neighbors) {
  vector<point> train2 = get_neighbors(train, test_row, num_neighbors);
  int len = train2.size();
  //string all_label[len];
  //int cnt = 0;
  map<string, int> label_num;
  int ans = 0;
  string ans_string;
  
  for (int i = 0; i < len; i++) {
    /*if (label_num[train2[i].label] == 0) {
      label_num[train2[i].label]++;
      all_label[cnt++] = train2[i];
    } else {
      label_num[train2[i].label]++;
    } */
    label_num[train2[i].label]++;
    if (label_num[train2[i].label] > ans) {
      ans = label_num[train2[i].label];
      ans_string = train2[i].label;
    }
    
  }
  
  return ans_string;
}

调用实现

# Test distance function
dataset = [[2.7810836,2.550537003,0],
	[1.465489372,2.362125076,0],
	[3.396561688,4.400293529,0],
	[1.38807019,1.850220317,0],
	[3.06407232,3.005305973,0],
	[7.627531214,2.759262235,1],
	[5.332441248,2.088626775,1],
	[6.922596716,1.77106367,1],
	[8.675418651,-0.242068655,1],
	[7.673756466,3.508563011,1]]

test=[2.5, 3.6]
num_neighbors = 3
label of test ?
point test_p;
test_p.x = 2.5, test_p.y = 3.6;
test_p.label = predict_classification(dataset, test_p, num_neighbors);

评价

让我写的这个就是一个简单的机器学习,通过临近的点预测这个点的label。比如我们有很多样本,可能不只有两个属性,比如老人、年轻人、小孩、男人、女人等等他们的喜好,通过类似这样的程序来根据新来的一个人的属性来推测他的喜好。当然现实中的程序会比这更复杂,我们做的就是从海量数据中分析预测当前输入的结果。
夸奖了我写代码的能力强,但是工作中主要用pythonJava,让我再学一下。

反问

Q:我是不是要再学习一下机器学习?
A:阿里是有专门的软件做这些,但是机器学习方面的ruaruaurabuabuabua(听不清的英语词)可以学习了解一下。
Q:什么时间出结果呀?
A:现在是周末,所以应该是下周吧。

总结

这次面试的体验超级棒!面试官非常友好,对我也比较满意。
昨天腾讯差点给我整自闭了,今天阿里给了我巨大的安慰。

三面

面试

形式:牛客视频面试。

工作介绍

主要是云监控。

自我介绍

计算机基础

Q:进程和线程?
A:梅开三度
Q:进程资源哪些是共享的,哪些是独有的?
A:我知道有一些方式可以实现进程间通讯,这不知道。
Q:排序都有哪些?
A:O(n2)的有冒泡和选择,O(nlogn)的有快排和归并。
Q:有没有更快的?
A:O(n)的不知道。
Q:桶排序?
A:用的不多,不太了解。
Q:数据库建表要考虑哪些?
A:要有主键,后面放其他信息,主键不能有重复的。

笔试

//评测题目:  二叉树序列化和反序列化
// define binary tree struct
// give tree struct => string
// string => tree struct

struct node {
  int val;
  node* left, right;
};
string s;

string treeToString(node* tree) {
  if (tree == null) return "!"; // end
  return intToString(tree -> val) + '@' + treeToString(tree -> left) + '@' + treeToString(tree -> right);
}

"4!!@2@5!!@1@3!!"

node* stringToTree(string s) {
  if (s == "!") return null;
  node* cur;
  
  
  //cur -> val = s[0];
  string sub_s;
  for (int i = 0; s[i] != '@';i++) {
    sub_s.push_back(s[i]);
  }
  cur -> val = stringToInt(sub_s);
  
  cur -> left = stringToTree(s);
  s = s.substring(sub_s.length());
  if (s != "")
    cur -> right = stringToTree(s);
  
  return cur;
}


   1
  / \
 2   3
/ \ 
4  5

没做过这种,开始没搞清楚他要干啥,写了很久。
开始写成中序遍历错了,于是改为前序遍历。

反问

Q:这份工作需要哪些技能?比如C++,进程之类?
A:前面问的都是你们上课学过的计算机基础问题,要实际看。
Q:后面还有多少面?
A:过了的话是一个交叉面和一个hr面,没过就又进简历池了。

总结

要凉要凉
更新:果真凉了


接下来更字节跳动面经,但是他要求实习4个月导致我有点不想去。
实习笔记:内网语雀

赞赏