SWE · Coding

恰两种无序平方和:枚举a≤b并饱和计数到3

包含a0和a=b,严格s<n,不把第三种表示误当两种。

题目重点:包含a0和a=b,严格s<n,不把第三种表示误当两种。

题意与假设

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

  • 非负整数a/b,(a,b)与(b,a)同一表示,允许a=b与0;返回全部s<n恰两种表示。
  • 原值域n可近2³¹,枚举代码是正确基线但不是对最大范围的可承诺性能方案,需讨论预算/分段或数论优化。

解题路线

  1. a到isqrt(n−1),b从a到isqrt(n−1−a²)。这刚好枚举每个无序合法pair一次。累加counts[s],超过2后饱和为3保留“至少3”状态。
  2. 最后选择count==2并排序。不能提前在第二次命中时输出,因为以后可能第三次出现;也不能饱和在2。
  3. 枚举区域是半个四分之一圆,pair数量Θ(n),不是只有外层√n就O(√n)。最大输入可能需数亿pair及巨大map,面试应明确此规模风险和优化目标。

手动走一遍

50=1²+7²=5²+5²,两种,输出50;25=0²+5²=3²+4²也两种。0仅(0,0)一种,不输出。末值n本身不包含,n50时50不输出。

Python 参考实现

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

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

from math import isqrt


def exactly_two(n):
    if type(n) is not int or n<1:raise ValueError("positive integer bound required")
    counts={}
    for a in range(isqrt(n-1)+1):
        for b in range(a,isqrt(n-1-a*a)+1):
            value=a*a+b*b;counts[value]=min(3,counts.get(value,0)+1)
    return sorted(value for value,count in counts.items() if count==2)

复杂度

枚举Θ(n)整数操作、map最坏O(n)条;排序O(AlogA),A输出数。大整数isqrt/乘法位成本另计。

易错点与追问

容易失分的边界

  • 漏a=0会漏平方数轴表示。
  • 用floor(sqrt(float))可能边界舍入,整数isqrt更稳。

继续深挖

  • 只查询单个s是否恰两种时怎样少枚举一个维度?
  • n很大而内存有限,如何分段累计并明确重复扫描成本?
✓已复制微信号!