Python技术迷

面试了40k的offer,HR要求提供流水,结果上家是25k每月,HR看了流水说只能给30k,直接把 offer拒了

刚看到个贴子,说朋友面到40k的offer,HR非要看流水,一看上家才25k,就反手改口只给30k,朋友当场拒了,走人。

Image

贴子内容本身不稀奇,流水压价这套,很多人都见过。问题在于,HR一边用“岗位值40k”钓你,一边又用“你之前只值25k”卡你,这逻辑本身就挺拧巴的。真要按历史工资算,那市场价还有啥意义?

从我的角度看,两边都能理解。30k不是不能接受,但关键在于,这已经不是钱多钱少的问题,而是信任崩了。就像买菜,标好价你付钱,结果老板看你穿得普通,临时给你涨价,谁心里能舒服?

不过话说回来,朋友敢拒,其实底气也来自自身能力。要是没实力,HR这一刀,你也只能硬吃。

面试题:直线上的最近距离

昨天晚上快十一点,我在公司楼下啃着个冷掉的汉堡,手机那边我们组小李突然发了个消息过来: “哥,你帮我看看这题咋写,直线上的最近距离,用 Python。”

我一看,这不就是那种典型的面试/笔试小算法嘛,其实思路挺简单,但要讲清楚也有点意思,就顺手给他录了几段语音。下面我就按当时跟小李聊天的感觉,给你也捋一遍。

先把题意说人话一点哈,一般这道题会长这样:

给你一堆点,都在一条直线上,用一个数组表示它们的位置,比如 points = [2, 10, 4, 7],每个数字就是这个点在数轴上的坐标(可以是负数,可以重复)。 让你求:任意两个点之间的最小距离是多少。

比如上面这个例子, 排序后是 [2, 4, 7, 10], 间距分别是 2, 3, 3, 所以最小距离就是 2(来自点 2 和点 4)。

题目还有几个默认小前提我一般会自己补一下:

  • 少于两个点就没法算距离,这种要么返回 None,要么约定返回 0,看你们业务怎么定义。
  • 坐标可能无序、可能重复、可能为负数,都要能扛得住。

刚开始你脑子里蹦出来的肯定是暴力做法:

反正也不多,就两层循环,每一对点都算一下距离,取个最小值就完了,对吧。

用 Python 写大概就是这样:

defmin_distance_bruteforce(points):
    n = len(points)
if n < 2:
returnNone# 或者返回 0,看题目要求

    ans = float('inf')
for i in range(n):
for j in range(i + 1, n):
            dist = abs(points[i] - points[j])
if dist < ans:
                ans = dist
return ans

这个写法逻辑上没问题,就是时间复杂度是 O(n²)。 如果 n 一大,像 10^5 级别的,直接超时给你看,线上也不可能这么写。

那怎么优化呢? 这里有一个非常关键的观察:

在一条直线上,最小距离一定出现在排序后相邻的两个点之间。

为啥?我用口语版证明跟小李说的那个:

你随便拿三个点,排序后是 a <= b <= c。

  • b 和 c 的距离是 c - b
  • a 和 c 的距离是 c - a = (c - b) + (b - a),肯定比 c - b 大
  • a 和 b 的距离是 b - a,它俩之间总有一个是这三个里最小的 不管怎样,这个“最小的距离”一定是出现在某一对相邻点之间。

把这个结论放大到 n 个点,意思就是: 你只需要把点排个序,然后只看相邻点之间的距离,就能找到全局最小距离了,完全没必要两两都比一遍。

所以整体步骤就是三步:

  1. 对数组排序,O(n log n)
  2. 一次扫一遍数组,计算 points[i] 和 points[i - 1] 的距离
  3. 保留最小值,O(n)

上代码:

defmin_distance(points):
    n = len(points)
if n < 2:
returnNone# 或者 0,按需求来

# 1. 排序
    points = sorted(points)

# 2. 扫一遍,找相邻差值最小的
    ans = float('inf')
for i in range(1, n):
        dist = points[i] - points[i - 1]  # 已排序,可不用 abs
if dist < ans:
            ans = dist

return ans

时间复杂度:O(n log n),真正耗时的就是排序那一步。 空间上除了排序用的那点,几乎没啥额外消耗。

顺手给小李测了几个例子:

print(min_distance([2, 10, 4, 7]))        # 2
print(min_distance([5, 5, 5]))            # 0(有重合点)
print(min_distance([-3, 0, 9, 10]))       # 1
print(min_distance([100]))                # None

要是哪一对点也想拿出来怎么办

一般面试官有时候还会加一句: “顺便把那一对距离最近的点也输出一下。”

这个也不难,在刚才那段代码上稍微扩展一下就行了,多记两个变量:

from typing import List, Optional, Tuple

defmin_distance_with_pair(points: List[int]) -> Optional[Tuple[int, int, int]]:
"""
    返回 (最小距离, 点1, 点2)
    """

    n = len(points)
if n < 2:
returnNone

    points = sorted(points)

    ans = float('inf')
    pair = (None, None)

for i in range(1, n):
        dist = points[i] - points[i - 1]
if dist < ans:
            ans = dist
            pair = (points[i - 1], points[i])

return ans, pair[0], pair[1]

比如:

print(min_distance_with_pair([2, 10, 4, 7]))
# 输出类似: (2, 2, 4)

这样题目一旦变形,你也不慌。

-END-

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

🔥虎哥私藏精品🔥

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