You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

LeetCode加热器问题解法的时间复杂度分析疑问

理解双指针解法的O(N+M)时间复杂度

首先先看你给出的LeetCode问题解法代码:

def findOptimalRadius(houses, heaters): 
    houses.sort() 
    heaters.sort() 
    last = len(heaters) - 1 
    x1,x2 = 0,0 
    res = 0 
    for house in houses: 
        while x2 < last and house > heaters[x2]: 
            x1, x2 = x2, x2+1 
        dist1,dist2 = abs(heaters[x1] - house), abs(heaters[x2] - house) 
        res = max(res, min(dist1,dist2)) 
    return res 

这是个非常好的问题!很多人刚接触双指针解法时,都会被这种嵌套循环的结构迷惑,误以为时间复杂度是O(N*M),但实际上这里的while循环有个核心优化点:指针x2只会单向前进,永远不会回退

我们来一步步拆解执行次数:

  • 外层的for循环会遍历每一个房屋,总共执行N次(N是房屋数量)。
  • 内层的while循环里,x2从0开始,每次循环只会将x2加1,最多只会走到last(也就是加热器数组的最后一个索引,即M-1)。换句话说,整个算法运行期间,while循环的总执行次数最多是M次——因为x2不可能从M-1往回走,每个加热器最多被访问一次。

举个直观的例子帮助理解:
假设houses = [1,4,6,8,10]heaters = [3,7,9]

  • 处理house=1:x2=0,1不大于3,while循环不执行。
  • 处理house=4:4>3,x2变成1,此时4不大于7,循环停止。
  • 处理house=6:6不大于7,while循环不执行。
  • 处理house=8:8>7,x2变成2,此时x2等于last(2),循环停止。
  • 处理house=10:10>9,但x2已经等于last,while循环不执行。

这里while循环总共只执行了2次,加上for循环的5次,总操作次数是7,接近N+M=5+3=8的规模(最多就是N+M次)。

对比暴力解法(每个房屋都遍历所有加热器找最近距离),那才是O(N*M)的时间复杂度,但这里利用了两个数组已排序的特性,让x2指针只单向移动,完全避免了重复遍历加热器,从而将遍历部分的时间复杂度降到了O(N+M)。

另外补充一点:整个算法的总时间复杂度其实是由排序步骤主导的,即O(N log N + M log M),因为排序的时间开销远大于后续遍历的O(N+M)。而你提到的空间复杂度差异,主要取决于排序算法的实现(比如Python内置的sort是Timsort,空间复杂度为O(N)和O(M)),所以会有数组已排序和未排序两种情况的区别。

内容的提问来源于stack exchange,提问作者user15102768

火山引擎 最新活动