看完2025职场新人报告,字节赢麻了

274 阅读5分钟

职场新人

正值校招火热进行时,职场 App 脉脉发布了一项有意思的数据分析报告,主要是针对"职场新人"的,这里说的新人,是指毕业三年内的同学。

这份报告,如果简单总结的话,就是字节赢麻了。

首先一个很直接的数据,2025 校招生里面,有近一半(43.37%)的学生,最想去的公司,就是字节,其次是腾讯和阿里。

十年前,是 BAT,十年后,还是 BAT。

只不过这里的 B,不是百度(Baidu),而是字节(ByteDance)。

这是只出现在 2025 校招生中的偶然吗,还是说近几年的年轻人,就是特别钟爱字节?

接下来一份职场新人(3 年以下经验)的流向企业,直面回答了这个问题。

这个图的看法是:流向该公司的新人,大多源自左边的公司,然后从该公司流出的新人,大多会去往右边的公司。

用第一项数据来举 🌰 的话,就是绝大多数跳槽到字节的新人,来源于快手、美团和腾讯,而从字节跳出去的新人,大多数都会去腾讯、美团和京东。

可以看出,除字节本身外的九家公司,有七家的大厂新人,最想跳槽的公司,就是字节。唯二的两家,阿里和网易,跳槽名单也有字节,只不过是排在第二。

说句字节是新人们的梦中情司,不过分。

这里面的原因,并不难想。

除了字节的薪资待遇很有竞争力以外,字节的企业文化,也是受年轻人们所喜爱的主要原因。

有 OKR,没有奋斗者氛围,有扁平化管理,没有江湖气,虽然也有一些"嫡系"的说法,但整体还是相对纯粹。

随着互联网主力人群的新老交替,我想绝大多数公司未来的企业文化,未来或多或少都会往"字节系"去靠拢。

...

说到字节,就来一道和「字节(校招二面)」相关的算法题。

题目描述

平台:LeetCode

题号:419

给你一个大小为 m×nm \times n 的矩阵 boardboard 表示甲板,其中,每个单元格可以是一艘战舰 'X' 或者是一个空位 '.' ,返回在甲板 boardboard 上放置的战舰的数量。

战舰只能水平或者垂直放置在 boardboard 上。

换句话说,战舰只能按 1×k1 \times k11 行,kk 列)或 k×1k \times 1kk 行,11 列)的形状建造,其中 kk 可以是任意大小。

两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。

示例 1:

输入:board = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]]

输出:2

示例 2:

输入:board = [["."]]

输出:0

提示:

  • m=board.lengthm = board.length
  • n=board[i].lengthn = board[i].length
  • 1<=m,n<=2001 <= m, n <= 200
  • board[i][j]board[i][j]'.''X'

进阶:你可以实现一次扫描算法,并只使用 O(1)O(1) 额外空间,并且不修改 board 的值来解决这个问题吗?

脑筋急转弯

如果「允许扫描多次」或者「使用与输入同规模的空间」的话,做法都十分简单:

  • 允许扫描多次,但空间只能 O(1)O(1):每次遇到 X 的格子,则将 X 所在的战舰修改为 -,统计完答案后,再扫描一次,将 - 恢复为 X 即可;
  • 扫描一次,但空间允许 O(m×n)O(m \times n):使用一个与矩阵同等大小的辅助数组 visvis 记录访问过的位置即可。

但题目要求「扫描一次」并且「空间 O(1)O(1)」,这就需要有点「脑筋急转弯」了。

注意这里的「扫描一次」是指使用一次遍历,而非要求每个单元格仅能访问一次,注意两者区别。

思考上述两种做法,我们本质 都是在战舰的首个格子进行计数,并将该战舰的所有格子进行处理,同时使用去重手段(原数组标记 或 使用辅助数组)来防止该战舰在后面遍历中被重复计数。

如果我们能够找到某种规律,直接判断出某个 X 格子是否为战舰开头,则不再需要其他去重手段。

当且仅当某个 X 格子的「上方」&「左方」不为 X 时,该格子为战舰首个格子,可以进行计数,同时需要注意当前当为 00(没有「上方」)和当前列为 00(没有「左方」)时的边界情况。

  • 一次扫描 + O(1)O(1) 代码:
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;
    }
}
  • 两次扫描 + O(1)O(1) 代码:
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;
    }
}
  • 一次扫描 + O(m×n)O(m \times n) 代码:
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;
    }
}