对实习leader有好感了,怎么办?
刚实习一个月,就把leader看成心动嘉宾了,这剧情搁职场里,多少有点危险。
喜欢成熟能干那挂,很正常。天天在工位上看人做事利索、说话稳、情绪还在线,滤镜本来就容易套上去。评论区也有人劝,“先别冲,八成是职场光环,不一定是真喜欢。”这话挺扎心,但真不算错。还有人更直接:“你以为是恋爱开场,人家可能只当你是实习生名单里的一个名字。”
现在最尴尬的点,不是加不加V,是你俩压根还没到私聊那一步。工作交流都还在群里,你突然单独去加,HR看了都得挑下眉。真想试,也别上来就暴露意图,先把业务接住,找点正常由头建立沟通。实习期先别把自己演成办公室偶像剧男主,转正都没影呢,先别把路走窄了。
算法题:单调递增的数字
这题最容易写歪的地方,不是代码,而是第一眼判断。
很多人一上来就想:从左到右扫一遍,只要当前位比后一位大,就把后一位改大一点,或者干脆一路凑 9。这种写法我一般第一眼就不太信。因为这题坑不在“找到下降点”,坑在你改完当前位,前一位可能也被连带搞坏了。
比如 332。
你如果只盯着最后那个 2,很容易改成 329、339 这种看着像那么回事的结果,但都不对。真正答案是 299。也就是说,这题不是简单修一位,而是可能要往前回退,回退完,后面再统一补 9。
先把题意压成一句人话:
给你一个非负整数 n,找一个小于等于它的最大整数,并且这个整数从左到右每一位都是单调不下降的。
像 1234、11239 这种都算。 像 120、332 就不算。
这题我一般不从数值下手,直接转字符串或者数组。原因很简单,位操作在这种“回退一位,再改后面所有位”的题里,写着写着就容易把自己绕进去。
先看关键判断:
defmonotone_increasing_digits(n: int) -> int:
arr = list(str(n))
mark = len(arr)
for i in range(len(arr) - 1, 0, -1):
if arr[i - 1] > arr[i]:
arr[i - 1] = str(int(arr[i - 1]) - 1)
mark = i
for i in range(mark, len(arr)):
arr[i] = '9'
return int(''.join(arr))
这个写法核心就两步。
第一步,从右往左找“破坏单调”的位置。为什么一定要从右往左?因为一旦前一位减了 1,新的前一位又可能和更前面的位产生新的下降关系。这个连锁反应,只能往前处理,不能往后补。
第二步,记录最后一次出问题的位置 mark,从这里开始,后面的数全改成 9。这地方别舍不得,后缀改成 9 才能保证“在不超过原数的前提下尽量大”。
拿 332 走一遍:
n = 332
# arr = ['3', '3', '2']
# i = 2,发现 arr[1] > arr[2]
# 第二个 '3' 变成 '2',mark = 2
# arr = ['3', '2', '2']
# i = 1,发现 arr[0] > arr[1]
# 第一个 '3' 变成 '2',mark = 1
# arr = ['2', '2', '2']
# 最后从 mark=1 开始全部置 9
# arr = ['2', '9', '9']
最后得到 299。
再看一个更容易看出“回退”味道的数:1234321。
你不能以为只把最后的 21 修一下就完了,实际中间那个 4 一旦降了,前面的关系也要重新检查。所以从右往左扫,是这题真正的手感,不是技巧,是必要条件。
顺手再补一个测试:
tests = [10, 1234, 332, 120, 1000, 1234321]
for x in tests:
print(x, '->', monotone_increasing_digits(x))
输出大概是:
10 -> 9
1234 -> 1234
332 -> 299
120 -> 119
1000 -> 999
1234321 -> 1233999
这题不难,难的是别被“看着能修一位”的错觉带偏。
我自己做这类数位题,有个很死的习惯:凡是出现“局部修改可能影响前面状态”的,优先考虑逆向扫。因为顺着写,十有八九会补一堆 if,最后代码能跑,脑子已经乱了。
这题就是典型代表。先退,再补 9,收工。