Python技术迷

今天去一家小公司面试,算是开了眼 公司藏在居民楼里,老板亲自开门,办公室直接设在客厅~

我在网上看到个吐槽帖:有人去一家小公司面试,地点先把人整不会了——公司开在居民楼里,老板亲自来开门,推门一看更绝,办公室就在客厅,挤挤巴巴放两张桌子,连老板自己都占着一个工位。

Image

有人说这种地方别急着嫌弃,自己在居民楼公司干了十年,舒服得很,不用跟人抢电梯,停车省事,穿个拖鞋就能上班,厨房还能自己做饭,班味都淡了不少。

我看完的感觉是,这种公司像开盲盒。外表确实不体面,第一眼容易劝退,可对有些人来说,它还真挺实用。尤其通勤轻松、规矩少这点,打工人到了后期,真比装修气派更管用。

算法题:轰炸敌人

这题我第一次看到名字还以为是模拟题,真下手写的时候,很容易先写成“遇到一个空位,就往四个方向扫一遍”。逻辑没错,但复杂度顶不住。 如果网格是 m * n,每个空位都上下左右扫,最坏会到 O(m*n*(m+n)),数据一大就开始发抖。

这题更适合换个看法:不是站在空位上找敌人,而是把一整段连续区域里的击杀数先算出来。 因为炸弹会沿着上下左右一直炸,直到碰到墙 W,所以同一段里,横向结果其实可以复用,纵向结果也可以复用。

比如这一行:

["0", "E", "E", "0", "W", "E"]

从左往右走,碰到墙之前,这一段里有几个 E,这件事没必要反复算。

我一般会这么写,两个变量够了:

  • row_hits:当前格子所在这段横向连续区间里有多少敌人
  • col_hits[j]:当前列从当前位置往下,到墙之前有多少敌人

代码不长,核心就是“只在需要时重算”。

from typing import List

classSolution:
defmaxKilledEnemies(self, grid: List[List[str]]) -> int:
ifnot grid ornot grid[0]:
return0

        m, n = len(grid), len(grid[0])
        col_hits = [0] * n
        ans = 0

for i in range(m):
            row_hits = 0
for j in range(n):
if j == 0or grid[i][j - 1] == 'W':
                    row_hits = 0
                    k = j
while k < n and grid[i][k] != 'W':
if grid[i][k] == 'E':
                            row_hits += 1
                        k += 1

if i == 0or grid[i - 1][j] == 'W':
                    col_hits[j] = 0
                    k = i
while k < m and grid[k][j] != 'W':
if grid[k][j] == 'E':
                            col_hits[j] += 1
                        k += 1

if grid[i][j] == '0':
                    ans = max(ans, row_hits + col_hits[j])

return ans

这段代码有个细节挺关键: 只有当前一个位置是墙,或者已经走到边界时,才重新统计这一段的数据。否则直接复用前面算好的结果。

拿这个例子跑一下:

grid = [
    ["0","E","0","0"],
    ["E","0","W","E"],
    ["0","E","0","0"]
]

print(Solution().maxKilledEnemies(grid))  # 3

为什么答案是 3? 因为中间几个空位里,左上角第一行第三列那个 0,横着能炸到 1 个,竖着能炸到 2 个,加起来正好 3。