7022. 限制条件下元素之间的最小绝对差

超时版

cs 复制代码
public class Solution {
    public int MinAbsoluteDifference(IList<int> nums, int x) {
      if(x == 0)
      {
        return 0;
      }

      // 初始为 int 最大值
      int ans = int.MaxValue;

      // 简单直接双层遍历
      int len = nums.Count - x;
      for(int i = 0; i < len; i++)
      {
        for(int j = i + x; j < nums.Count; j++)
        {
          ans = Math.Min(ans, Math.Abs(nums[j] - nums[i]));
        }
      }
      return ans;
    }
}

超时版:

参考:借助一个有序集合保存可匹配的有序元素集合,再根据当前元素,快速找到这个元素在这个集合中的左右边界

问题:这里 查找 边界元素导致超时,需要优化

cs 复制代码
public class Solution {
    public int MinAbsoluteDifference(IList<int> nums, int x) {
      if(x == 0)
      {
        return 0;
      }

      // 初始为 int 最大值
      int ans = int.MaxValue;

      // 存储可匹配的元素,支持有序插入
      SortedSet<int> set = new SortedSet<int>();
      for(int i = x; i < nums.Count; i++)
      {
        int val = nums[i];

        // 将相隔x的元素插入
        set.Add(nums[i - x]);

        // 获取边界值
        (int low, int high) = GetBound(set, val);
        if(low != -1)
        {
          ans = Math.Min(ans, Math.Abs(val - low));
        }
        if(high != -1)
        {
          ans = Math.Min(ans, Math.Abs(val - high));
        }
      }
      return ans;
    }

    // 获取 set 中 小于等于, 大于val的元素
    public (int low, int high) GetBound(SortedSet<int> set, int val) {
      if(set.Count == 0)
      {
        return (-1, -1);
      }

      int low = -1;
      int high = -1;
      foreach(var s in set)
      {
        if(s <= val)
        {
          low = s;
          continue;
        }

        high = s;
        break;
      }
      return (low, high);
    }
}

这里使用 GetViewBetween 获取部分的节点遍历,但再最后两个测试数据中超时。

目前看,最好的办法时,可以改写SortedList,提供一个获取边界的方法,源码中其实已经包含类似的方法(FindNode),只是没有提供外界使用

cs 复制代码
public class Solution {
    public int MinAbsoluteDifference(IList<int> nums, int x) {
      if(x == 0)
      {
        return 0;
      }

      // 初始为 int 最大值
      int ans = int.MaxValue;

      // 存储可匹配的元素,支持有序插入
      SortedSet<int> set = new SortedSet<int>();
      for(int i = x; i < nums.Count; i++)
      {
        int val = nums[i];

        // 将相隔x的元素插入
        set.Add(nums[i - x]);

        // 获取边界值
        (int low, int high) = GetBound(set, val);
        if(low != -1)
        {
          ans = Math.Min(ans, Math.Abs(val - low));
        }
        if(high != -1)
        {
          ans = Math.Min(ans, Math.Abs(val - high));
        }
      }
      return ans;
    }

    // 获取 set 中 小于等于, 大于val的元素
    public (int low, int high) GetBound(SortedSet<int> set, int val) {
      if(set.Count == 0)
      {
        return (-1, -1);
      }

      int low = -1;
      int high = -1;
    
      // 数量太大时,获取部分
      if(set.Count > 1000)
      {
        set = set.GetViewBetween(val - 100000, val + 100000);
      }
      foreach(var s in set)
      {
        if(s <= val)
        {
          low = s;
          continue;
        }

        high = s;
        break;
      }
      return (low, high);
    }
}

参考版:

相关推荐
专注仿真5 小时前
知识问答模型用到的算法集详解及代码实例
python·算法·代码·大模型训练·控制算法
罗西的思考6 小时前
【轻量化复刻大模型 / KIMI K3】AttnRes 模块交互式演示
人工智能·算法·机器学习
好悬给我拽开线9 小时前
ZILOT 论文解析
算法
饮水桶_T10 小时前
JAVA IO流笔记
开发语言·数据结构·算法
星夜离尘5611 小时前
MATLAB 离散数据分箱:半开区间、末端点与计数、加权和、平均
算法·matlab
Pniubi11 小时前
力扣76.最小覆盖子串
算法·leetcode·职场和发展
地平线开发者12 小时前
征程6|用 hrt\_model\_exec 看清 YOLOv5x 的输入、原始输出和后处理
人工智能·算法
csdn_aspnet13 小时前
C++ 3个有序点的方向(Orientation of 3 ordered points)
c++·算法
赤生云电竞13 小时前
GPU算力共享平台架构实践:任务分发与资源隔离的关键配置
算法·架构·gpu算力
青少儿编程课堂14 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:折半搜索优化子集枚举(Meet in the Middle)解析
c++·python·算法·bfs·信息学竞赛