阿里这次笔试选择题跟编程题难度完全不是一个级别的(附题解)
选择题做得想哭(严格来说是还没哭出来就自动交卷了)
编程题居然能全AC提前交卷,那么多次笔试这是第一次
算法岗两道编程题,一道是八卦阵,矩阵中有八个不相连的区域,每个区域由相邻的大于零的数字组成,区域与区域之间由零隔开,求这些区域的和的最大值和最小值是多少。
思路是遍历矩阵,寻找不为0的值,那么它一定在某个区域内,从它所在的位置开始搜索这个区域的所有值,求和,顺便将搜索过的值置为0。
#include <cstdio>
#include <algorithm>
#include <climits>
using namespace std;
int **mat;
int m, n;
int single(int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n || mat[i][j] == 0)
return 0;
int t = mat[i][j];
mat[i][j] = 0;
for (int a = -1; a <= 1; a++)
for (int b = -1; b <= 1; b++)
t += single(i + a, j + b);
return t;
}
int main() {
scanf("%d", &m);
scanf("%d", &n);
mat = new int*[m];
for (int i = 0; i < m; i++)
mat[i] = new int[n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
scanf("%d", &mat[i][j]);
int zmax = INT_MIN, zmin = INT_MAX;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
if (mat[i][j] != 0) {
int t = single(i, j); zmax = max(zmax, t);
zmin = min(zmin, t);
}
}
printf("%d\n%d\n", zmax, zmin);
return 0;
}
一道是寻找有向图中这样的一个结点,从这个结点出发的路径数量是最多的。
思路是,如果结点a有两条出边,a->b,a->c,那么从a出发的路径数量=从b出发的路径数量+从c出发的路径数量+2(a->b,a->c两条边本身也是路径)。所以直接遍历从a的出边,递归计算出边指向的结点的路径数量,然后求和即可。
如果简单地dfs,会重复搜索,即如果有a->c,b->c,那么会搜索c两次。所以要把c的计算结果保存下来。这里通过数组vis来保存,第i位为-1表示没有计算过从节点i出发的路径数量。也就是所谓的记忆化搜索。
#include <cstdio> #include <algorithm> #include <climits> #include <vector> using namespace std; int N; int M; int vis[10000]; vector<int> m[10000]; int traverse(int n) { if (vis[n] != -1) return vis[n]; int t = 0; for (int i = 0; i < m[n].size(); i++) { t = t + traverse(m[n][i]) + 1; } vis[n] = t; return t; } int main() { scanf("%d", &N); for (int i = 0; i < N; i++) vis[i] = -1; int t; scanf("%d%d", &M, &t); for (int i = 0; i < M; i++) { int a, b; scanf("%d%d", &a, &b); m[a].push_back(b); } int zmax = INT_MIN; int zi = 0; for (int i = 0; i < N; i++) { t = traverse(i); if (t > zmax) { zi = i; zmax = t; } } printf("%d\n", zmax); return 0; }#实习##阿里巴巴##笔试题目#