Python技术迷

对实习leader有好感了,怎么办?

刚实习一个月,就把leader看成心动嘉宾了,这剧情搁职场里,多少有点危险。

Image

喜欢成熟能干那挂,很正常。天天在工位上看人做事利索、说话稳、情绪还在线,滤镜本来就容易套上去。评论区也有人劝,“先别冲,八成是职场光环,不一定是真喜欢。”这话挺扎心,但真不算错。还有人更直接:“你以为是恋爱开场,人家可能只当你是实习生名单里的一个名字。”

现在最尴尬的点,不是加不加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,收工。