在职4年多,归还电脑时,因为有4个角磕碰,要收我 275块钱。真真恶心我呀。
刚看到个贴子,说一网友在职四年多,离职还电脑,因为四个角有磕碰,公司要收他275块钱,他气得直说“真恶心”。
我觉得关键在两个点:第一,这算正常损耗还是人为损坏?第二,入职时有没有写在资产协议里、折旧规则有没有说清楚。正常磨损全砸员工头上,确实不地道;但真是自己用得太糙,该担的责任也不能全往外推。
从我的角度看,公司老拿这种小钱卡人,只会把员工的好感和信任一点点磨光;打工人也得长心眼,领设备时拍照留底,交接要有记录,有争议就拿事实说话。
算法题:在 LR 字符串中交换相邻字符
昨天晚上十一点多吧,我在楼下抽烟(别学啊…咳),群里有人突然丢了个题:就一串只含 L 和 R 的字符串,规则特别像排队插队——只要看到相邻的 "LR",你就能把它交换成 "RL"。然后他问我:那这玩意儿到底怎么写得又快又稳,别一上来就暴力模拟到天亮那种。
我当时第一反应其实是线上故障那种“数据包粘一起”的感觉,你们懂吧,就是你以为一次只来一个阶段,结果它俩挤一块儿来了,解析就炸。这个题也一样,你以为交换就是换一下,实际一轮里很多对会同时发生,得小心“重叠”——比如 "LLRR" 里中间那俩一换,指针走错就会重复换或者漏换。
先说最朴素的:模拟“一轮交换”(同一轮里,不能让刚换出来的新字符继续参与本轮),写法就是用指针 i 扫过去,遇到 "LR" 就输出 "RL" 并且 i += 2,不然就输出当前字符 i += 1。这个很像我写协议解析时的“读够了就跳两个字节”…嗯跑题了。
defone_round_swap(s: str) -> str:
# 一轮:把不重叠的 "LR" 交换成 "RL"
out = []
i = 0
n = len(s)
while i < n:
if i + 1 < n and s[i] == 'L'and s[i + 1] == 'R':
out.append('R')
out.append('L')
i += 2
else:
out.append(s[i])
i += 1
return''.join(out)
defsimulate_until_stable(s: str, limit: int = 10_000) -> tuple[str, int]:
# 一直做一轮轮交换,直到稳定(没有 "LR")
steps = 0
for _ in range(limit):
ns = one_round_swap(s)
if ns == s:
return s, steps
s = ns
steps += 1
raise RuntimeError("可能是limit太小,或者输入不对劲")
但你要是问“要几轮才稳定”,我跟你说,真不用一直模拟。你把这个过程想成:每一轮,某个 R 最多只能往左挪 1 格(因为只能跟左边的 L 交换)。所以最终稳定形态其实就是所有 R 都跑到左边、所有 L 去右边。那稳定需要的轮数,就是“最倒霉的那个 R,它左边一开始有多少个 L 需要跨过去”的最大值。
扫描一遍就行:从左到右数 L 的数量 cntL,每遇到一个 R,它要跨过的 L 就是当前 cntL,取最大就是轮数;顺便把这些 cntL 累加起来,其实就是总交换次数(逆序对数量),有时候也挺有用。
defmin_rounds_to_stable(s: str) -> int:
cntL = 0
ans = 0
for ch in s:
if ch == 'L':
cntL += 1
elif ch == 'R':
ans = max(ans, cntL)
else:
raise ValueError("只允许L/R")
return ans
deftotal_swaps_needed(s: str) -> int:
cntL = 0
inv = 0
for ch in s:
if ch == 'L':
cntL += 1
elif ch == 'R':
inv += cntL
else:
raise ValueError("只允许L/R")
return inv
随便举个例子你就有感觉了:"LLRLRR",前两个 R 左边各有 2 个 L,后面那个 R 左边有 3 个 L,所以最少要 3 轮才彻底没有 "LR"。你要真用 simulate_until_stable 跑,也会是 3。就那种“你以为只是换个相邻字符”,结果背后其实是个并行版冒泡,唉我当时困得要死还跟群里解释半天。
行了我先不说了…我这边外卖到了,等下凉了又得挨老婆骂。