破产套路已经从三件套升到了七件套。。
刚刷到这个“中产破产七件套”,我第一反应是:这不就是很多人把日子过成项目失控吗?
以前说破产三件套,已经够吓人了。现在直接升级,创业一冲动,房贷一背上,家里再少一个收入来源,孩子教育还得往死里卷。然后手里有点钱又想翻倍,基金、股票、项目听着都香,真亏起来比谁都安静。
最扎心的是,很多人还不把身体当回事。熬夜、应酬、硬扛,觉得自己还能撑。结果一个检查单下来,前面算的账全白算。
再加上攀比消费,车要像样,房要体面,孩子要高级,朋友圈也不能输。看着是中产生活,其实每一步都在加杠杆。风一吹,现金流先跪了。打工人看完真有点沉默,这哪是七件套,简直是人生连环坑。
[5, 5] 和 [6, 3] 放一起,第一眼很容易写错。
这个题坑不在“弱角色”三个字,坑在 攻击力和防御力都必须严格小于另一个角色。只要有一个相等,就不能算。
题目给的是一堆角色属性:
properties = [[5, 5], [6, 3], [3, 6]]
每个角色两个值:
[攻击力, 防御力]
如果存在另一个角色,攻击力比它高,防御力也比它高,那这个角色就是弱角色。
比如:
[3, 6]
攻击力比 [5, 5] 低,但防御力比它高,所以不是弱角色。
[6, 3]
攻击力很高,但防御力低,也不是。
这题要是直接双层循环,当然能写:
for i in range(n):
for j in range(n):
...
但是数据量一大,这代码基本就不用看了,O(n²),线上跑批见到这种我一般先皱眉。算法题里也一样,能过小样例,不代表能过隐藏用例。
这题我会先排序。
关键点是排序规则:
攻击力从大到小排
攻击力相同,防御力从小到大排
注意第二个规则,不是随手写的。
为什么攻击力相同的时候,防御力要从小到大?
因为攻击力相同的两个角色,不能互相判定为弱角色。题目要求攻击力也要严格大于。如果同攻击力里把防御力大的放前面,后面防御力小的就可能被误判。
看这个数据:
[[5, 10], [5, 1]]
它们攻击力一样,谁也不能吃掉谁。
所以排序必须这么写:
properties.sort(key=lambda x: (-x[0], x[1]))
排完以后,我们从左往右扫。
因为前面的攻击力一定大于等于当前角色。由于同攻击力已经按防御力升序排过,所以当前角色只要发现前面出现过更大的防御力,就说明前面一定存在一个攻击力更高、防御力也更高的角色。
代码我一般会写成这样:
from typing import List
classSolution:
defnumberOfWeakCharacters(self, properties: List[List[int]]) -> int:
properties.sort(key=lambda item: (-item[0], item[1]))
max_defense_seen = 0
weak_count = 0
for attack, defense in properties:
if defense < max_defense_seen:
weak_count += 1
else:
max_defense_seen = defense
return weak_count
拿一组数据过一下:
properties = [[7, 9], [7, 3], [6, 8], [5, 2], [4, 10]]
排序后大概是:
[[7, 3], [7, 9], [6, 8], [5, 2], [4, 10]]
扫到 [7, 3],前面没有更强的,记录最大防御力是 3。
扫到 [7, 9],同攻击力不能算弱,更新最大防御力为 9。
扫到 [6, 8],前面已经有 [7, 9],攻击力更高,防御力也更高,所以它是弱角色。
扫到 [5, 2],也弱。
扫到 [4, 10],防御力比之前最大值 9 还高,不弱。
这里比较容易误写成:
properties.sort(key=lambda item: (-item[0], -item[1]))
这行我不太信。
因为它会让同攻击力里防御力大的排前面,然后小的被 max_defense_seen 压住,直接算错。
这题真正要记的不是排序 API,而是这个判断顺序:
先保证攻击力维度不会乱,再用一个历史最大防御力把第二个维度压住。
时间复杂度是排序的 O(nlogn),后面只扫一遍。空间上除了排序本身,不需要额外开一堆数组。
这种题看着像比较两个字段,实际是在考你会不会处理“相等字段不能误伤”。排序题里,最烦的往往就是这个相等条件。