职场新人
正值校招火热进行时,职场 App 脉脉发布了一项有意思的数据分析报告,主要是针对"职场新人"的,这里说的新人,是指毕业三年内的同学。
这份报告,如果简单总结的话,就是字节赢麻了。
首先一个很直接的数据,2025 校招生里面,有近一半(43.37%)的学生,最想去的公司,就是字节,其次是腾讯和阿里。
十年前,是 BAT,十年后,还是 BAT。
只不过这里的 B,不是百度(Baidu),而是字节(ByteDance)。
这是只出现在 2025 校招生中的偶然吗,还是说近几年的年轻人,就是特别钟爱字节?
接下来一份职场新人(3 年以下经验)的流向企业,直面回答了这个问题。
这个图的看法是:流向该公司的新人,大多源自左边的公司,然后从该公司流出的新人,大多会去往右边的公司。
用第一项数据来举 🌰 的话,就是绝大多数跳槽到字节的新人,来源于快手、美团和腾讯,而从字节跳出去的新人,大多数都会去腾讯、美团和京东。
可以看出,除字节本身外的九家公司,有七家的大厂新人,最想跳槽的公司,就是字节。唯二的两家,阿里和网易,跳槽名单也有字节,只不过是排在第二。
说句字节是新人们的梦中情司,不过分。
这里面的原因,并不难想。
除了字节的薪资待遇很有竞争力以外,字节的企业文化,也是受年轻人们所喜爱的主要原因。
有 OKR,没有奋斗者氛围,有扁平化管理,没有江湖气,虽然也有一些"嫡系"的说法,但整体还是相对纯粹。
随着互联网主力人群的新老交替,我想绝大多数公司未来的企业文化,未来或多或少都会往"字节系"去靠拢。
...
说到字节,就来一道和「字节(校招二面)」相关的算法题。
题目描述
平台:LeetCode
题号:419
给你一个大小为 的矩阵 表示甲板,其中,每个单元格可以是一艘战舰 'X' 或者是一个空位 '.' ,返回在甲板 上放置的战舰的数量。
战舰只能水平或者垂直放置在 上。
换句话说,战舰只能按 ( 行, 列)或 ( 行, 列)的形状建造,其中 可以是任意大小。
两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。
示例 1:
输入:board = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]]
输出:2
示例 2:
输入:board = [["."]]
输出:0
提示:
- 是
'.'或'X'
进阶:你可以实现一次扫描算法,并只使用 额外空间,并且不修改 board 的值来解决这个问题吗?
脑筋急转弯
如果「允许扫描多次」或者「使用与输入同规模的空间」的话,做法都十分简单:
- 允许扫描多次,但空间只能 :每次遇到
X的格子,则将X所在的战舰修改为-,统计完答案后,再扫描一次,将-恢复为X即可; - 扫描一次,但空间允许 :使用一个与矩阵同等大小的辅助数组 记录访问过的位置即可。
但题目要求「扫描一次」并且「空间 」,这就需要有点「脑筋急转弯」了。
注意这里的「扫描一次」是指使用一次遍历,而非要求每个单元格仅能访问一次,注意两者区别。
思考上述两种做法,我们本质 都是在战舰的首个格子进行计数,并将该战舰的所有格子进行处理,同时使用去重手段(原数组标记 或 使用辅助数组)来防止该战舰在后面遍历中被重复计数。
如果我们能够找到某种规律,直接判断出某个 X 格子是否为战舰开头,则不再需要其他去重手段。
当且仅当某个 X 格子的「上方」&「左方」不为 X 时,该格子为战舰首个格子,可以进行计数,同时需要注意当前当为 (没有「上方」)和当前列为 (没有「左方」)时的边界情况。
- 一次扫描 + 代码:
class Solution {
public int countBattleships(char[][] board) {
int m = board.length, n = board[0].length;
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i > 0 && board[i - 1][j] == 'X') continue;
if (j > 0 && board[i][j - 1] == 'X') continue;
if (board[i][j] == 'X') ans++;
}
}
return ans;
}
}
- 两次扫描 + 代码:
class Solution {
public int countBattleships(char[][] board) {
int m = board.length, n = board[0].length;
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] != 'X') continue;
board[i][j] = '-';
for (int k = i + 1; k < m && board[k][j] == 'X'; k++) board[k][j] = '-';
for (int k = j + 1; k < n && board[i][k] == 'X'; k++) board[i][k] = '-';
ans++;
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == '-') board[i][j] = 'X';
}
}
return ans;
}
}
- 一次扫描 + 代码:
class Solution {
public int countBattleships(char[][] board) {
int m = board.length, n = board[0].length;
int ans = 0;
boolean[][] vis = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] != 'X' || vis[i][j]) continue;
vis[i][j] = true;
for (int k = i + 1; k < m && board[k][j] == 'X'; k++) vis[k][j] = true;
for (int k = j + 1; k < n && board[i][k] == 'X'; k++) vis[i][k] = true;
ans++;
}
}
return ans;
}
}