You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化基于Fenwick Tree的最长递增子序列(LIS)解法性能?

优化Fenwick Tree实现严格递增LIS的核心方案

1. 替换冗余逻辑:用离散化去重替代路径检查+前置极小值

  • 问题根源:原方案中的前置极小值和路径检查会引入额外遍历与条件判断,拖慢性能。
  • 优化操作:
    • 对输入数组做排序去重得到有序唯一数组,将原数组元素映射到该数组的索引(转换为Fenwick Tree的1-based索引)。
    • 利用二分查找确定当前元素的查询范围:对于元素x,用bisect_left找到其在唯一数组中的位置idx,则比x小的所有元素对应Fenwick Tree的1~idx区间,直接查询该区间最大值即可保证严格递增,无需额外路径检查。
    • 移除序列头部的极小值:离散化后的索引天然适配Fenwick Tree从1开始的特性,初始状态下Fenwick Tree所有节点值为0,第一个元素查询结果为0,更新后值为1,逻辑完全自洽。

2. 优化Fenwick Tree的实现细节

  • 最大值型Fenwick Tree的高效实现:
    • 采用数组直接存储树结构,避免类成员函数的额外开销(若用面向对象语言,可将核心操作内联或简化)。
    • 更新操作提前终止:在更新节点时,若当前节点已有值大于等于要更新的值,直接终止向上更新——因为Fenwick Tree父节点存储的是区间最大值,当前节点无变化时,父节点的最大值也不会改变,这能大幅减少循环次数。
    • 查询操作极简逻辑:遍历前缀区间时仅记录最大值,避免不必要的计算。

示例代码(Python):

import bisect

def get_sorted_unique(arr):
    sorted_arr = sorted(arr)
    unique = []
    prev = None
    for num in sorted_arr:
        if num != prev:
            unique.append(num)
            prev = num
    return unique

class FenwickTree:
    def __init__(self, size):
        self.n = size
        self.tree = [0] * (self.n + 2)  # 预留额外空间避免越界
    
    def update(self, idx, value):
        while idx <= self.n:
            if self.tree[idx] < value:
                self.tree[idx] = value
            else:
                break  # 无需继续向上更新
            idx += idx & -idx
    
    def query(self, idx):
        res = 0
        while idx > 0:
            if self.tree[idx] > res:
                res = self.tree[idx]
            idx -= idx & -idx
        return res

def strict_lis_length(arr):
    if not arr:
        return 0
    sorted_unique = get_sorted_unique(arr)
    ft = FenwickTree(len(sorted_unique))
    max_len = 0
    for num in arr:
        idx = bisect.bisect_left(sorted_unique, num)
        current = ft.query(idx) + 1
        ft.update(idx + 1, current)
        if current > max_len:
            max_len = current
    return max_len

3. 离散化的性能优化

  • 避免使用set去重:对于大规模数组,直接排序后遍历去重比先转set再排序更高效,减少哈希表的构建开销。
  • 用内置高效二分实现:比如Python的bisect模块(底层C实现),比手动写二分查找快很多。

性能对比

优化后的方案将时间复杂度稳定在O(NlogN),和线段树实现的复杂度一致,但Fenwick Tree的常数更小(代码更简洁、内存占用更低、操作步骤更少),实际运行效率会优于线段树实现。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 09:02:08