程序员老鬼

月薪2万,在大厂干了10年被裁了,拿了30万赔偿金,五年后HR联系我,问我愿不愿意回去,但要归还30万,这种情况该回去吗?

刚看到个贴子:网友月薪2万在大厂干了10年,被裁拿了30万赔偿。过了五年,HR又来问要不要回去,但前提是——把当年的30万还回去。问该不该回?

Image

网友回帖我看了看,有的说“说明你值钱,赶紧回”、也有的骂公司抠门,“再给双倍都不回”。怎么说呢,我的看法是:可以考虑回去,但绝不能糊里糊涂把钱退了。

赔偿金是当年解除劳动关系的“分手费”,那是对你过去十年付出的补偿,不是预支工资,更不是借款。五年之后再说“你想复合就把分手费退了”,从情理上就说不通,何况职场本来就是契约关系,不是谈恋爱图感动。

真想回,也得重新谈:岗位、薪资、晋升空间,算清现在和未来值不值,而不是被所谓“老东家情怀”绑架。

面试题:有效的井字游戏

有次面试,我正讲着自己怎么优化接口,面试官突然来一句:那你顺手写下“有效的井字游戏”这题吧。看起来是个小游戏,对吧,3×3 的棋盘,X 和 O,你一下我一下,谁先连成一条线谁赢。结果真下笔的时候,好多人就开始翻车了。

所以今天就聊聊这个题,顺便用 Java 把它写清楚。

题目一般会给你一个 3 行字符串的数组,比如:

["XOX",
 " XO",
 "   "]

空格表示没下子,X 先手,X 和 O 轮流下。问的是:这种局面,合不合理?也就是“从空棋盘开始,按照规则一步一步走,能不能走到现在这个样子”。

那什么叫“违规”的状态呢?你可以先脑补几个明显不对的:

  • O 的数量比 X 还多,那肯定不行,因为永远是 X 先下。
  • X 和 O 数量差超过 1,也不行,因为大家轮流下嘛。
  • O 已经赢了,但棋盘上 X 的子还比 O 多,这说明 O 赢了以后还有人继续胡乱下。
  • X 赢了,但 X 和 O 数量一样多,也说不通,赢的一方一定是刚多下的那个。

其实核心就两块:数一数棋子个数,再看看谁赢了。

我习惯先写个小工具函数,判断某个玩家有没有已经“三连”。在 Java 里就这么搞:

privatebooleanwin(char[][] b, char p){
// 三行
for (int i = 0; i < 3; i++) {
if (b[i][0] == p && b[i][1] == p && b[i][2] == p) {
returntrue;
        }
    }
// 三列
for (int j = 0; j < 3; j++) {
if (b[0][j] == p && b[1][j] == p && b[2][j] == p) {
returntrue;
        }
    }
// 两条对角线
if (b[0][0] == p && b[1][1] == p && b[2][2] == p) {
returntrue;
    }
if (b[0][2] == p && b[1][1] == p && b[2][0] == p) {
returntrue;
    }
returnfalse;
}

这个函数就是个“裁判”:传进来棋盘和某个字符,比方说 'X',就告诉你 X 有没有已经连成一条线。

然后整个题的逻辑其实就几点

  1. 遍历一遍棋盘,把 X 的数量记成 xCount,O 的数量记成 oCount。
  2. 因为 X 先手,所以要么两个人一样多,要么 X 比 O 多一个。否则直接非法。
  3. 判断一下 xWin = win(board, 'X'),oWin = win(board, 'O')。
  4. 如果两个人同时赢了,这种棋盘肯定不可能从正常对局走出来,非法。
  5. 如果 X 赢了,那它一定是刚刚多走那一步,所以必须满足 xCount == oCount + 1。
  6. 如果 O 赢了,那它一定刚走完,所以必须满足 xCount == oCount。
  7. 其他情况就是合法。

整合一下 Java 代码,大概是这样:

publicclassSolution{

publicbooleanvalidTicTacToe(String[] boardStr){
char[][] board = newchar[3][3];
int xCount = 0;
int oCount = 0;

// 把 String[] 先转成 char[][],顺便统计棋子数量
for (int i = 0; i < 3; i++) {
            board[i] = boardStr[i].toCharArray();
for (int j = 0; j < 3; j++) {
if (board[i][j] == 'X') {
                    xCount++;
                } elseif (board[i][j] == 'O') {
                    oCount++;
                }
            }
        }

// 数量规则:X 先手,所以要么一样多,要么 X 多一个
if (!(xCount == oCount || xCount == oCount + 1)) {
returnfalse;
        }

boolean xWin = win(board, 'X');
boolean oWin = win(board, 'O');

// 不可能同时赢
if (xWin && oWin) {
returnfalse;
        }

// X 赢了,那一定是 X 刚多下那一步
if (xWin && xCount != oCount + 1) {
returnfalse;
        }

// O 赢了,那一定是 O 刚下完这一手
if (oWin && xCount != oCount) {
returnfalse;
        }

// 其他情况都合法
returntrue;
    }

privatebooleanwin(char[][] b, char p){
// 行
for (int i = 0; i < 3; i++) {
if (b[i][0] == p && b[i][1] == p && b[i][2] == p) {
returntrue;
            }
        }
// 列
for (int j = 0; j < 3; j++) {
if (b[0][j] == p && b[1][j] == p && b[2][j] == p) {
returntrue;
            }
        }
// 主对角线
if (b[0][0] == p && b[1][1] == p && b[2][2] == p) {
returntrue;
        }
// 副对角线
if (b[0][2] == p && b[1][1] == p && b[2][0] == p) {
returntrue;
        }
returnfalse;
    }
}

你可以自己在脑子里跑几个例子:

  • 全空棋盘:X 和 O 都是 0 个,没人赢,合法。
  • 只有一个 X 在中间:xCount = 1, oCount = 0,没人赢,合法。
  • O 比 X 多:比如一堆 O,一个 X,这种一看就非法,前面数量判断直接卡掉。
  • 棋盘上 X 有三连,但 X 和 O 数量一样多,这种就被 “X 赢了但数量没对上” 这条规则干掉。

这题表面是个小游戏,实际在考你能不能把“规则”翻译成“条件判断”。以后碰到类似“是否为合法状态”的题,基本套路也差不多:先还原规则,再一点点翻译成 if。这样你再遇到别的棋类、游戏的“状态是否合法”,心里就有数了。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

最后给大家分享一份不错的副业资料,点击下方公众号,回复关键字: 副业 领,也可以链接我微信:hls404