Python技术迷

大厂违约金汇总一览表~

刚看到个贴子在讨论“大厂违约金汇总表”,不少人吐槽得挺激烈的。怎么说呢,违约金这事,每家公司标准不一样,但核心矛盾其实就一个——签的时候都爽快,真要履约了,很多人又想反悔。

Image

我觉得这事吧,网友们的回帖我也看了,有说公司霸王条款的,也有说求职者太天真的。

但从我的角度看,成年人就得为自己的选择负责。签字那一刻,就说明默认规则了

当然,有些不合理的违约金标准是应该被讨论、被监督的,但只要是双方同意的合同,临到头了耍赖、想钻空子的,那就是不讲规矩。

说到底,违约金不是罚心情,是为了约束双方,不让谁说走就走、说变就变。守诺,是成年人的底线;遵守规则,才能让职场更公平

面试题:最小因式分解

先说题目哈,其实“最小因式分解”这道题的意思,大概是这样:

给你一个正整数 n,想办法把它拆成若干个 2~9 之间的整数相乘,比如n = 48 = 2 * 2 * 2 * 2 * 3 = 6 * 8。 然后再把这些因子当成“数字”拼在一起,组成一个新的整数,让这个新整数尽量小。 如果怎么拆都不行,就返回 -1。用 Python 写。

我一般会先把题脑补成几个例子,你也可以一起想一下:

  • n = 15因数只能用 2~9,那就只有 3 * 5,能拼的数有:35 或 53,最小的是 35。

  • n = 48可以拆成:2 * 2 * 2 * 2 * 3,也可以 6 * 8。 如果用 2,2,2,2,3 拼的话,排序后是 22223; 用 6,8 拼,排序后是 68,明显 68 更小。 所以我们直觉上就有一个感觉:尽量用大一点的因子,能减少“位数”,最后拼出的数会更小。

再看一个失败的例子:

  • n = 1111 本身是质数,而且比 9 大,又不能用 1,只能用 2~9,那就没法拆,答 -1。

到这里,题目的感觉就比较清晰了。

算法的核心思路(很朴素的贪心)

大方向其实就一句话:

从 9 一直往下试到 2,能整除就把这个因子拿走,最后看能不能刚好除尽。

一步一步来拆:

  1. 特殊情况先处理一下:

  • 如果 n 本来就在 0~9 之间(比如 2、7 这种),它自己就是答案(一般题目会约定 n>1,你可以按题意调整)。
  • 从 9 开始往下枚举到 2:

    • 把 d 记到一个数组里,比如 factors.append(d)
    • n //= d
    • 只要当前因子 d 能整除 n,就:

    • 一直除到不能再除为止,再换下一个更小的因子。

  • 枚举完 9~2 之后:

    • 如果这时候 n 还大于 1,说明有残余质因子 > 9,没办法拆,直接返回 -1。
    • 否则说明拆成功了,factors 里面全是 2~9 的数字。
  • 注意一个小细节:

    • 我们是从 9 往 2 拆的,所以 factors 里面的数字是从大到小的。
    • 但要拼成“最小的数字”,肯定要从小到大排。
    • 这时候只要把 factors 反转一下,或者排序一下再拼接就行了。

    为什么“先用大的因子”是对的? 直觉上很好理解:把 8 拆成 2 * 2 * 2,位数立马从 1 位变成 3 位,哪怕每位都很小,整体数字反而会变大。 所以优先用大的因子,是一种很自然的贪心策略。

    defsmallest_factorization(n: int) -> int:
    """
        把正整数 n 分解成若干个 2~9 的因子
        再把这些因子按从小到大拼成一个最小整数
        如果无解返回 -1
        """

    # 特殊情况:n 本来就是一位数
    if n >= 0and n < 10:
    return n

        factors = []

    # 从 9 一直试到 2,能除就一直除
    for d in range(9, 1, -1):
    while n % d == 0:
                factors.append(d)
                n //= d

    # 如果最后 n 还剩下一个 >1 的因子,说明拆不干净
    if n != 1:
    return-1

    # 此时 factors 里是从大到小的数字,比如 [9, 4]
    # 为了拼出最小整数,我们要从小到大拼,比如 [4, 9] -> 49
        factors.reverse()

    # 把数字列表拼成真正的整数
        res = 0
    for d in factors:
            res = res * 10 + d
    # 这里如果有 32 位整型限制,可以顺便判断一下
    if res > 2**31 - 1:
    return-1

    return res


    if __name__ == "__main__":
        tests = [15, 48, 11, 36, 100]
    for x in tests:
            print(x, "=>", smallest_factorization(x))

    你可以自己跑一下,大概会看到类似结果(具体跟题目要求可能略有差别,但思路就是这个):

    • 15 => 35
    • 48 => 68
    • 11 => -1
    • 36 => 49(4 * 9 = 36)
    • 100 => 455(4 * 5 * 5 = 100,拼成 455)

    复杂度顺带说一下

    • 外层从 9 到 2 就 8 个数字,常数级。
    • 内层 while 每除一次,n 就会缩小一截,理论上最多也就 O(log n) 次。
    • 所以整体时间复杂度可以认为是 O(log n),空间就是存一下那些因子,O(log n) 级别。

    整体来说算是很典型的一道“贪心 + 因数分解”的小题,思路想通了,代码其实就那么几行。你要是愿意再扩展一下,还可以顺手写个普通的“质因数分解”函数,对比一下两种玩法的差别。

    -END-

    我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

    🔥虎哥私藏精品🔥

    虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB