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

已排序列表拆分:满足最大长度m与容差k的最少子列表数优化

问题与解决方法

需求与问题

给定已排序整数列表x,需计算满足以下条件的最少子列表数量:

  • 子列表长度 ≤ m
  • 子列表中最小元素 + 2k ≥ 最大元素
    无需生成子列表,仅统计数量。

当前实现的split函数计算出的子列表数量偏高,核心问题在于拆分逻辑过于保守,没有尽可能让每个子列表容纳最多的合法元素。

原代码

def split(x,k,m,n):
    time = 0
    if n<=m:
        try:
            if x[-1]<=x[0]+2*k:
                time +=1
            else:
                time += split(x[0:n-1],k,m,n-1)
                time += split(x[n-1:n],k,m,1)
        except:
            pass
    else:
        time += split(x[0:n-m],k,m,n-m)
        time += split(x[n-m:n],k,m,m)
    return time

原代码问题分析

  1. 当列表长度n>m时,直接硬切最后m个元素,完全不考虑这部分元素是否满足数值条件,可能导致不必要的拆分。
  2. 当n<=m时,若整体不满足数值条件就拆分为前n-1个和最后1个元素,这种拆分方式会大幅增加子列表数量,因为没有尝试找到更大的合法子列表。

最优实现(贪心算法)

由于输入列表是已排序的,贪心策略是最优选择:从左到右遍历,每个子列表尽可能延伸到最大的合法位置,确保每个子列表容纳最多元素,从而最小化总数量。

def min_subarrays(x, k, m):
    count = 0
    n = len(x)
    i = 0
    while i < n:
        count += 1
        start_val = x[i]
        # 先根据长度限制确定最远可能位置
        max_pos = min(i + m - 1, n - 1)
        # 再根据数值条件往左调整到最远合法位置
        while max_pos > i and x[max_pos] > start_val + 2 * k:
            max_pos -= 1
        # 跳到下一个子列表的起点
        i = max_pos + 1
    return count

算法说明

  1. 每次从当前位置i开始,将x[i]作为子列表的最小元素。
  2. 先根据长度限制m确定最远可能的位置max_pos(不超过i+m-1,也不超出列表范围)。
  3. 由于列表已排序,从max_pos往左找第一个满足x[max_pos] ≤ start_val + 2k的位置,这个位置就是当前子列表的最远终点。
  4. 计数加1,然后从终点的下一个位置开始处理剩余元素,直到遍历完整个列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 06:55:14