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);
    }
}

参考版:

相关推荐
金融小师妹1 小时前
基于哈塞特独立性表态的AI量化研究:美联储政策独立性的多维验证
大数据·人工智能·算法
纪元A梦4 小时前
贪心算法应用:化工反应器调度问题详解
算法·贪心算法
阿让啊5 小时前
C语言strtol 函数使用方法
c语言·数据结构·c++·单片机·嵌入式硬件
深圳市快瞳科技有限公司5 小时前
小场景大市场:猫狗识别算法在宠物智能设备中的应用
算法·计算机视觉·宠物
liulilittle5 小时前
OPENPPP2 —— IP标准校验和算法深度剖析:从原理到SSE2优化实现
网络·c++·网络协议·tcp/ip·算法·ip·通信
superlls8 小时前
(算法 哈希表)【LeetCode 349】两个数组的交集 思路笔记自留
java·数据结构·算法
田里的水稻8 小时前
C++_队列编码实例,从末端添加对象,同时把头部的对象剔除掉,中的队列长度为设置长度NUM_OBJ
java·c++·算法
纪元A梦8 小时前
贪心算法应用:保险理赔调度问题详解
算法·贪心算法
Ripple123129 小时前
数据结构:顺序表与链表
数据结构·链表
Jayden_Ruan9 小时前
C++逆向输出一个字符串(三)
开发语言·c++·算法