超时版
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);
}
}
参考版: