算法题题解记录——双变量问题的 “枚举右,维护左”

算法题的时间复杂度是必须考虑的因素,n的数量级和复杂度二者可以决定算法的执行时间。在有进行时间限制的题中,一个过于复杂的题解会因超时而得不到全分。

本文记录了对观光景点组合得分问题的思考、分析和优化。

题目

www.marscode.cn/practice/r3...

方法一:BF

思路

这道题的暴力解法是采用 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2) 的遍历,枚举所有的两两组合,取最大值。

代码

python 复制代码
def solution(values: list) -> int:
    # PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
    # write code here

    ans = 0
    l = len(values)
    for i in range(l):
        for j in range(i + 1, l):
            ans = max(ans, values[i] + values[j] + i - j)

    return ans


if __name__ == '__main__':
    print(solution(values=[8, 3, 5, 5, 6]) == 11)
    print(solution(values=[10, 4, 8, 7]) == 16)
    print(solution(values=[1, 2, 3, 4, 5]) == 8)

复杂度

  • 时间复杂度 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2)
  • 空间复杂度 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( 1 ) O(1) </math>O(1)

思考优化点

这道题是leetcode第1014题,在力扣中明确提到了n最大可以取到 <math xmlns="http://www.w3.org/1998/Math/MathML"> 5 ∗ 1 0 4 5 * 10^4 </math>5∗104。而 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2) 的算法会执行 <math xmlns="http://www.w3.org/1998/Math/MathML"> 25 ∗ 1 0 8 25*10^8 </math>25∗108,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> 2.5 ∗ 1 0 9 2.5*10^9 </math>2.5∗109 次,而现代处理器大约能够每秒执行 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 0 8 10^8 </math>108 到 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 0 9 10^9 </math>109 次基本操作。 因此通常认为如果超过 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 0 9 10^9 </math>109 则超时

既然超时,那就一定存在不必要的重复计算,暴力求解的方法哪里重复计算了呢?请看图:

我们对 values[i] + values[j] + i - j 重新组合为values[i] + i + values[j] - j,会发现:对于固定的ji < j,只要 values[i] + i 越大,结果越大。而当 j 移动到 j+1 时,前 j - 1value[i] + i 的最大值已经计算过了。

显然这里可以优化。

方法二:

思路

既然左侧的 values[i] + i 存在重复计算,那显然我们可以用变量将其保存起来。然后在单次循环中进行最大值的维护。

这个思路被叫做双变量问题 的 "枚举右,维护左"。详见文章末尾。

代码

python 复制代码
def solution(values: list) -> int:
    # PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
    # write code here
    ans = 0
    mx = values[0] + 0
    for j in range(1, len(values)):
        ans = max(ans, mx + values[j] - j)
        # 边遍历边维护
        mx = max(mx, values[j] + j)
    return ans


if __name__ == '__main__':
    print(solution(values=[8, 3, 5, 5, 6]) == 11)
    print(solution(values=[10, 4, 8, 7]) == 16)
    print(solution(values=[1, 2, 3, 4, 5]) == 8)

复杂度

  • 时间复杂度 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(n) </math>O(n)
  • 空间复杂度 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( 1 ) O(1) </math>O(1)

总结

由数据范围反推算法复杂度以及算法内容

一般ACM或者笔试题的时间限制是1秒或2秒。 在这种情况下,C++代码的操作次数控制在10⁷~10⁸为最佳。 下面给出在不同数据范围内,代码的时间复杂度和算法该如何选择:

  1. n ≤ 30,指数级别,dfs+剪枝,状态压缩dp
  2. n ≤ 100,= O(n³),floyd,dp,高斯消元
  3. n ≤ 1000,= O(n²),O(n²logn),dp,二分,朴素版Dijkstra、朴素版Prim、Bellman-Ford
  4. n ≤ 10000,= O(n * √n),块状链表、分块、莫队
  5. n ≤ 100000,= O(nlogn),各种sort,线段树、树状数组、set/map、heap、拓扑排序、dijkstra+heap、prim+heap、Kruskal、spfa、求凸包、求半平面交、二分、CDQ分治、整体二分、后缀数组、树链剖分、动态树
  6. n ≤ 1000000 => O(n),以及常数较小的O(nlogn) 算法 => 单调队列、hash、双指针扫描、BFS、并查集、kmp、AC自动机,常数较小的O(nlogn)的做法: sort、树状数组、heap、dijkstra、spfa
  7. n ≤ 10000000,= O(n),双指针扫描、kmp、AC自动机、线性素数筛
  8. n ≤ 10⁹ => O(√n),判断质数
  9. n ≤ 10¹⁸ => O(logn),最大公约数,快速幂,数位DP
  10. n ≤ 10¹⁰⁰⁰ => O((logn)²),高精度加减乘除
  11. n ≤ 10¹⁰⁰⁰⁰⁰ => O(logk × loglogk),k表示位数,高精度加减、FFT/NTT

枚举右,维护左

对于 双变量问题 ,例如两数之和 aᵢ + aⱼ = t,可以枚举右边的 aⱼ,转换成 单变量问题 ,也就是在 aⱼ 左边查找是否有 aᵢ = t - aⱼ,这可以用哈希表维护。 这个技巧叫做 枚举右,维护左

参考文章:

www.acwing.com/blog/conten...

leetcode.cn/circle/disc...

相关推荐
海思开发板总店14 分钟前
openRv1126 AI算法部署实战之——Tensorflow模型部署实战
人工智能·算法·tensorflow
汤姆和佩琦38 分钟前
2025-1-28-sklearn学习(47) & (48) 万家灯火亮年至,一声烟花开新来。
人工智能·python·学习·机器学习·sklearn
讓丄帝愛伱40 分钟前
Java 泛型<? extends Object>
java·开发语言·python
985小水博一枚呀1 小时前
【论文推荐|深度学习,滑坡检测,多光谱影像,自然灾害,遥感】2022年Landslide4Sense竞赛成果:基于多源卫星影像的先进滑坡检测算法研究(五)
大数据·人工智能·深度学习·算法·cnn
Dr_Si1 小时前
CF 764B.Timofey and cubes(Java实现)
java·算法·排序算法
上海迪士尼351 小时前
RRT_STAR路径规划代码
人工智能·算法·matlab
金融OG1 小时前
99.20 金融难点通俗解释:中药配方比喻马科维茨资产组合模型(MPT)
大数据·数据库·人工智能·python·机器学习·金融
纠结哥_Shrek2 小时前
PyTorch 与 Python 版本对应关系
人工智能·pytorch·python
Lostgreen2 小时前
线性回归简介:从理论到应用
python·机器学习·回归·线性回归