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

寻求最少移位的原地数组压缩算法

实现最少移动量的Lua数组压缩算法

要实现最少元素移动次数的数组压缩(用-1标记空值),核心思路是用双指针法精准填补前面的空位,避免不必要的元素移动。具体逻辑如下:

  1. 用左指针left跟踪第一个未被填补的空位(值为-1的位置)
  2. 用右指针right从left的下一位开始遍历,找到第一个非-1的元素
  3. 找到后将该元素移动到left位置,把原位置设为-1,然后left右移一位(因为这个空位已经被填补)
  4. 重复上述过程直到遍历结束,最后清理数组末尾的所有-1(设为nil,保证Lua数组的正常迭代)

这种方法的移动次数是最少的——每个非-1元素最多被移动一次,只有当它需要填补前面的空位时才会被移动,完全符合你给出的示例效果。

Lua代码实现

local function compact(arr)
    local left = 1
    local len = #arr

    -- 第一步:填补前面的空位
    while left <= len do
        -- 找到第一个空位
        while left <= len and arr[left] ~= -1 do
            left = left + 1
        end
        -- 从left之后找第一个非-1元素
        local right = left + 1
        while right <= len and arr[right] == -1 do
            right = right + 1
        end
        -- 如果没有找到可移动的元素,结束循环
        if right > len then
            break
        end
        -- 移动元素到空位,原位置设为-1
        arr[left] = arr[right]
        arr[right] = -1
        left = left + 1
    end

    -- 第二步:清理末尾的-1,设为nil
    local last_valid = 0
    for i = 1, len do
        if arr[i] ~= -1 then
            last_valid = i
        else
            break -- 前面的空位已被填补,后续都是连续的-1
        end
    end
    -- 截断数组,把后面的元素设为nil
    for i = last_valid + 1, len do
        arr[i] = nil
    end
end

-- 测试示例
local arr = {1,3,4,-1,6,-1,8,-1,-1}
compact(arr)
-- 输出结果:{1,3,4,8,6}
for k, v in ipairs(arr) do
    print(v)
end

效果说明

拿你的示例来看:

  • 初始left停在索引4(值为-1),right找到索引7的8,将8移到4的位置,7设为-1,left移到5
  • 索引5的值是6(非-1),left继续移到6,此时right从7开始找,后面都是-1,循环结束
  • 最后清理时,从索引6开始都是-1,所以设为nil,最终数组就是{1,3,4,8,6},只移动了1次元素,完全符合预期。

相比反向遍历的方法,这种双指针法不会盲目移动所有元素,而是只针对性填补前面的空位,最大化减少移动次数,同时时间复杂度保持O(N),满足你的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:03:27