Python技术迷

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

刚看到个贴子:楼主月薪2万在大厂干了10年,被裁拿了30万赔偿。五年后原公司HR来电话,说可以回去,但得把当年的赔偿吐出来,问值不值得回。

Image

网友回复挺分裂的,有人说30万本来就是人家“施舍”,现在愿意再要你就偷着乐;也有人觉得这公司没底线,让你退钱说明压根没把员工当人看。

我觉得这事关键在一个字:值。赔偿是当年合法给你的,不存在“借”这一说,除非公司现在给到远高于市场的待遇和职位,你自愿把那30万当做“投资”,否则真没必要。换个角度想,五年里你如果有本事在别处混得不错,那说明你不缺这家大厂;如果这些年一直不顺,跟其说是回厂,不如说是给自己一个重新起步的机会。

力

算法题:有效的井字游戏

我直接说结论啊:这道“有效的井字游戏”,本质就是——别被棋盘骗了,只看两件事:落子数合不合理、胜负结果合不合理,就完事了。

那天晚上加班,到点了还在等一个接口压测结果,我就拿白板随手画了个井字棋跟小同事对划。画着画着他突然问我一句:“东哥,要是给你一个最终棋盘,让你判断这个局面是不是游戏过程中能走出来的,你咋写?”

我一想,咦,这不是正儿八经的算法题嘛,在 LeetCode 里就叫:有效的井字游戏(Valid Tic-Tac-Toe State)。

题目长这样,简单说人话就是:

  • 棋盘 3x3,用字符串数组 board = ["XOX"," XO","   "] 这种表示
  • X 先手,两个人轮流下,只有 X 和 O 两种子
  • 有人三连(横竖斜都算)就赢了,游戏可以提前结束
  • 问你:现在这个棋盘,有没有可能是按规则一手一手下出来的

你想啊,真实对局里有个最铁的规则:轮流下,也就是:

  • 因为 X 先手,所以 X 的个数要么比 O 多 1,要么刚好一样多
  • 不可能出现 O 比 X 多,也不可能 X 比 O 多 2 个以上

翻成代码就是先扫一遍棋盘:

x_count = sum(row.count('X') for row in board)
o_count = sum(row.count('O') for row in board)

# 数量不对,直接假
if o_count > x_count:
returnFalse
if x_count - o_count > 1:
returnFalse

到这,所有“摆造型”的假棋盘,比如全是 O、或者 X 一排 O 一排那种,都能先筛掉一大半。

数完子以后,就要问一句:有没有人已经三连了?

这时候写个小函数就行,八条线挨个检查:三行、三列、两条对角线。

defwin(ch: str) -> bool:
    b = board
# 三行
for i in range(3):
if b[i][0] == b[i][1] == b[i][2] == ch:
returnTrue
# 三列
for j in range(3):
if b[0][j] == b[1][j] == b[2][j] == ch:
returnTrue
# 两条斜线
if b[0][0] == b[1][1] == b[2][2] == ch:
returnTrue
if b[0][2] == b[1][1] == b[2][0] == ch:
returnTrue
returnFalse

有了 win('X') 和 win('O') 之后,接下来几个坑一定要卡住:

  1. 两个人不可能同时赢

    • 真对局里,只要有人先三连,游戏就结束了,不会再给另一个人下出一条三连线
    • 所以:if x_win and o_win: return False
  2. 如果是 X 赢了

    • 说明最后一步一定是 X 下的
    • 所以 此时必须满足:x_count == o_count + 1
    • 否则就是“赢完了还让 O 多下了一手”,假局面
  3. 如果是 O 赢了

    • 最后一步是 O 下的
    • 所以必须:x_count == o_count
    • 不然就变成 O 落后还赢,违背轮流规则
  4. 如果谁都没赢

    • 那就只看数量关系:
    • 前面已经保证过 x_count == o_count 或 x_count == o_count + 1,那就可以认为是合法过程中的某一帧

整个逻辑串起来其实就几句判断,但一堆人挂在“赢了之后还能继续下几步”这种边界上。

上完整代码,直接能跑,用的是 Python,类型注解你爱写就写,不写也行:

from typing import List

classSolution:
defvalidTicTacToe(self, board: List[str]) -> bool:
# 1. 统计 X 和 O 的个数
        x_count = sum(row.count('X') for row in board)
        o_count = sum(row.count('O') for row in board)

# 轮流规则:X 先手,X 要么等于 O,要么多 1
if o_count > x_count:
returnFalse
if x_count - o_count > 1:
returnFalse

# 2. 判断某个玩家是否已经三连
defwin(ch: str) -> bool:
            b = board
# 行
for i in range(3):
if b[i][0] == b[i][1] == b[i][2] == ch:
returnTrue
# 列
for j in range(3):
if b[0][j] == b[1][j] == b[2][j] == ch:
returnTrue
# 对角线
if b[0][0] == b[1][1] == b[2][2] == ch:
returnTrue
if b[0][2] == b[1][1] == b[2][0] == ch:
returnTrue
returnFalse

        x_win = win('X')
        o_win = win('O')

# 3. 胜负与落子数是否匹配
# 不可能双方都赢
if x_win and o_win:
returnFalse

# X 赢:必须比 O 多下一手
if x_win and x_count != o_count + 1:
returnFalse

# O 赢:必须和 X 手数相同
if o_win and x_count != o_count:
returnFalse

# 其他情况就是合法局面
returnTrue

你可以自己随便构造几个棋盘试试,比如:

  • ["XXX","OO ","   "] → X 三连了,而且 X=3, O=2,合法
  • ["XXX","OOO","   "] → 双方都赢了,直接判假
  • ["XOX"," X ","   "] → 数量不满足(O 太少或太多)也会被前面挡掉

这类题的套路啊,说白了就是:把游戏规则拆成几条 if,然后死磕边界,别想一口气写个“超聪明”的神奇公式。

行了,我先去泡杯咖啡,你要是后面想练习别的博弈类题,比如四子棋、五子棋那种判断胜负的,我们再慢慢唠。