Sr MLE · Phone Coding

LinkedIn 有序数组二次函数变换:双指针线性排序

代入 ax²+bx+c 后不直接再排序,利用抛物线两端极值按 a 的符号从外向内填充。

题目重点:代入 ax²+bx+c 后不直接再排序,利用抛物线两端极值按 a 的符号从外向内填充。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 输入升序整数数组,可重复;a、b、c 为整数,输出升序。训练代码使用 Python 无限精度整数;固定字长语言应评估 ax² 溢出。

解题路线

  1. 二次函数 a>0 时开口向上,输入区间两端中的较大变换值是剩余区间的最大值;用左右指针比较两端,较大者从结果末尾向前填。
  2. a<0 时开口向下,剩余最小变换值在两端;比较两端较小者,从结果头部向后填。a=0 是单调线性函数,a≥0 的端点最大值倒序填法仍适用。
  3. 每轮消费一个端点,剩余输入仍是连续有序区间,归纳保证当前选出的极值放在正确输出位置。
  4. 直接映射再排序 O(N log N) 是可读基线;若长度很短或面试无性能要求,先给基线并解释线性优化。

手动走一遍

A=[-4,-2,2,4]、f(x)=x²:两端 16/16 先填末尾,再 4/4,结果 [4,4,16,16]。若 f(x)=−x²,则两端先给最小的 −16,结果 [−16,−16,−4,−4]。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def sorted_quadratic(values: list[int], a: int, b: int, c: int) -> list[int]:
    n = len(values)
    result = [0] * n
    left, right = 0, n - 1
    write = n - 1 if a >= 0 else 0
    step = -1 if a >= 0 else 1

    def f(x):
        return a * x * x + b * x + c

    while left <= right:
        lv, rv = f(values[left]), f(values[right])
        if a >= 0:
            if lv >= rv:
                result[write] = lv
                left += 1
            else:
                result[write] = rv
                right -= 1
        else:
            if lv <= rv:
                result[write] = lv
                left += 1
            else:
                result[write] = rv
                right -= 1
        write += step
    return result

复杂度

O(N) 时间、O(N) 输出空间,额外指针 O(1)。30,000 组随机数组及系数与独立映射排序结果一致。

易错点与追问

容易失分的边界

  • a<0 仍按较大端点倒序填。
  • 以顶点为界分别排序两半,增加不必要成本。
  • a=0 且 b<0 时误以为输出保持输入顺序。
  • 两个端点相等时双消费,导致漏元素。
  • 固定宽整数计算 x² 溢出。

继续深挖

  • a=0 时结果方向怎么判断?
  • 如果输入是降序如何改?
  • 大量重复值对算法有影响吗?
  • 函数改成三次多项式还能两指针吗?
✓已复制微信号!