某公司技术leader:如果你不想加班,周日不看消息,想准时上下班的,请离开我的团队,这里不养大爷!
刚看到个贴子,说某公司技术leader放话:不想加班、不看周末消息、想准点上下班的,直接走人,这里不养大爷。
我作为程序员看这话,第一反应是:技术团队靠的是效率和创造力,不是靠拼命刷工时。代码不是搬砖,加班多了,Bug 也会多,最后修复成本更高。网友有人觉得“leader说的也没错,团队需要拼劲”,但我觉得这话太片面了。拼劲不能等于透支,职场不是无限体力赛。
从我的角度看,真正的好leader应该会思考如何提升团队产出,而不是简单用加班堆。就像写程序,设计架构才是关键,不是行数越多越牛。一个只靠加班维持的团队,说明管理和规划上已经失衡。【备注:文末可领最新资料】
面试题:数组的上界
昨天晚上十一点多在客厅找遥控器,手一摸手机就弹来个题:说“数组的上界怎么写?”我当时还困得眼冒金星,但这玩意儿其实挺好说的——就是那个…在一个已排序的数组里,找“第一个严格大于目标值”的位置。听着有点拗口?你把数组想成排队的人,目标值是身高 x,上界就是队伍里第一个比 x 高的人站的下标。没找到,就说明全都不比他高,那就返回队伍末尾的位置(也就是数组长度),表示插到最后也不坏规矩。
两个常见用处:一是给数组里插数据还保持有序,二是统计“有多少元素 ≤ x”,因为上界的位置 pos 本质上就是这样的个数。顺嘴一提,lower bound 是“第一个 ≥ x”,上界是“第一个 > x”,俩是亲兄弟,但不一样哈。
二分就行。我们维护一个半开区间 [l, r),一直缩,直到 l == r。中点 m 上的值和 x 比:
如果 a[m] <= x,说明答案在右边(要找第一个大于的),l = m + 1否则 a[m] > x,答案在左边含m,r = m
最后返回 l 就是答案。空数组?直接返回 0。全小于等于 x?返回 n。全大于 x?返回 0。都对劲。
defupper_bound(a, x):
l, r = 0, len(a) # 半开区间 [l, r)
while l < r:
m = (l + r) // 2
if a[m] <= x:
l = m + 1
else:
r = m
return l
# 小测一下
if __name__ == "__main__":
arr = [1, 2, 2, 2, 3, 5]
for t in [0, 1, 2, 4, 5, 6]:
print(t, "->", upper_bound(arr, t))
# 结果解释:
# 0 -> 0 (第一个>0在下标0)
# 1 -> 1 (第一个>1在下标1)
# 2 -> 4 (三个2都不>2,第一个>2是3,在下标4)
# 4 -> 5 (第一个>4是5,在下标5)
# 5 -> 6 (没有>5,返回len=6)
# 6 -> 6 (同理)
和 lower bound 一墙之隔
有时候你会搞混,我也会,半夜更会。记个小口诀:“等号给 lower”。也就是:
# lower bound: 第一个 >= x
deflower_bound(a, x):
l, r = 0, len(a)
while l < r:
m = (l + r) // 2
if a[m] < x:
l = m + 1
else:
r = m
return l
于是区间 [lower_bound(x), upper_bound(x)) 就是所有等于 x 的元素所在范围,计数也就 ub - lb,不需要在数组里来回扫。
标准库偷个懒
写比赛自己撸,写业务图省心,Python 直接用:
import bisect
pos = bisect.bisect_right(arr, x) # 这就是上界
# lower bound 对应 bisect.bisect_left(arr, x)
bisect_right 返回插入点,恰好是“第一个 > x”的下标,用来插入也稳当。
第一,必须升序,二分的单调性才成立;降序的话要么翻转,要么改判定,别混着用。第二,边界写 [l, r) 比较不容易死循环,m = (l + r) // 2 配合前面的两条更新规则就很顺。第三,整型溢出在 Python 不用担心,但在别的语言要注意 mid = l + (r - l) / 2 的写法。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领