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

参考版:

相关推荐
汀、人工智能3 小时前
[特殊字符] 第21课:最长有效括号
数据结构·算法·数据库架构·图论·bfs·最长有效括号
Boop_wu3 小时前
[Java 算法] 字符串
linux·运维·服务器·数据结构·算法·leetcode
故事和你913 小时前
洛谷-算法1-2-排序2
开发语言·数据结构·c++·算法·动态规划·图论
Fcy6484 小时前
算法基础详解(三)前缀和与差分算法
算法·前缀和·差分
kvo7f2JTy4 小时前
基于机器学习算法的web入侵检测系统设计与实现
前端·算法·机器学习
List<String> error_P4 小时前
蓝桥杯最后几天冲刺:暴力大法(一)
算法·职场和发展·蓝桥杯
迈巴赫车主5 小时前
蓝桥杯3500阶乘求和java
java·开发语言·数据结构·职场和发展·蓝桥杯
流云鹤5 小时前
Codeforces Round 1090 (Div. 4)
c++·算法
wljy16 小时前
第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(个人见解,已完结)
c语言·c++·算法·蓝桥杯·stl
高一要励志成为佬6 小时前
【数据结构】算法复杂度
数据结构