Algorithm 如何在删除/添加/更新元素后连续检查数组是否已排序

Algorithm 如何在删除/添加/更新元素后连续检查数组是否已排序,algorithm,Algorithm,假设给定了一个由n个整数组成的列表(该列表不需要已经排序)。在删除、更新或插入值后,如何检查列表是否已排序(非递增或非递减) 我唯一能想到的解决这个问题的方法是保留一个数字的链表,包括删除[O(n)]、插入[O(n)]和更新[O(n)]操作,以及一个线性检查,以查看其排序是非递减还是非递增。有可能更快地解决这个问题吗 移除、插入和更新意味着用户将给出移除/插入/更新的位置,并且将在给定位置插入、移除或添加值 在输入上随时会有一个查询,询问列表的状态(非递增或非递减) 在删除(假设代码没有做任何傻

假设给定了一个由n个整数组成的列表(该列表不需要已经排序)。在删除、更新或插入值后,如何检查列表是否已排序(非递增或非递减)

我唯一能想到的解决这个问题的方法是保留一个数字的链表,包括删除[O(n)]、插入[O(n)]和更新[O(n)]操作,以及一个线性检查,以查看其排序是非递减还是非递增。有可能更快地解决这个问题吗

移除、插入和更新意味着用户将给出移除/插入/更新的位置,并且将在给定位置插入、移除或添加值

在输入上随时会有一个查询,询问列表的状态(非递增或非递减)


删除
(假设代码没有做任何傻事)后,列表仍应排序,以便解决问题。对于
插入
,编写函数以便在正确的位置添加新元素。将
更新
视为
删除
,然后是
插入
。如果您确实希望遵循“is it ordered”标准,请使用闭包来确定两个列表元素是否有序,然后将列表划分为两个重叠的对,并将闭包映射到结果对集上。如果贴图不包含错误结果,表明所有重叠对都是有序的,则为金色

在Clojure(Lisp变体)中实现时,如下所示:

(defn is-ordered? [c f]
  "Determines if a collection is in sorted order as defined by the function f.
   c is a collection
   f is a function which accepts a collection for an argument, returning
   true if the collection is 'ordered' by  f's definition of 'ordered', and false
   if not."
  (not (contains? (set (map f (partition 2 1 c))) false)))

祝您好运。

您可以使用自动二进制搜索来获得最佳性能

例如:

类内部列表:IEnumerable
{
私有静态只读T[]空=新T[0];
私有int版本;
私有整数大小;
私人物品;
私人IComparer比较器;
public InternalList():此(0,null){}
公共内部列表(int capacity):此(capacity,null){}
公共内部列表(int容量、IComparer比较器)
{
如果(容量<0)
{
抛出新ArgumentOutOfRangeException(“容量”);
}
this.items=(容量==0)?空:新的T[容量];
this.comparer=comparer??comparer.Default;
}
公共作废新增(T项)
{
如果(大小==项目长度)
{
调整数组大小(参考项,(大小==0?4:大小*2));
}
int index=搜索(项目);
如果(索引!=大小)
{
复制(项目,索引,项目,索引+1,大小-索引);
}
项目[索引]=项目;
大小++;
版本++;
}
公共无效删除(整数索引)
{
如果(索引<0 | |索引>=大小)
{
抛出新的IndexOutOfRangeException();
}
如果(索引!=大小-1)
{
复制(项目,索引+1,项目,索引,(大小-索引)-1);
}
项目[--大小]=默认值(T);
版本++;
}
公共空间清除()
{
如果(大小!=0)
{
数组。清除(项目,0,大小);
尺寸=0;
版本++;
}
}
公共IEnumerator GetEnumerator()
{
返回新的枚举数(此);
}
专用整数搜索(T项)
{
如果(大小==0)
{
返回0;
}
int x=0;
int y=尺寸;
while(true)
{
int d=(y-x)/2;
int n=比较器。比较(项目[x+d],项目);
if(n<0)
{
如果(d==0)
{
返回x+1;
}
x+=d;
继续;
}
否则,如果(n>0)
{
如果(d==0)
{
返回x;
}
y-=d;
继续;
}
返回x+d;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
返回新的枚举数(此);
}
公共结构枚举器:IEnumerator
{
私人名单;
私有int版本;
私有整数索引;
私人T电流;
内部枚举器(内部列表)
{
this.list=列表;
this.version=list.version;
这个指数=-1;
this.current=默认值(T);
}
公共电流
{
得到
{
如果(索引==-1)
{
抛出新的InvalidOperationException();
}
回流;
}
}
对象IEnumerator.Current
{
获取{返回当前;}
}
公共图书馆
{
如果(版本!=列表.版本)
{
抛出新的InvalidOperationException();
}
如果(索引
但是,如果列表预计很长,并且添加内容预计不合逻辑,那么使用
System.Generic.SortedList
可能更明智,假设您使用的是DotNET


关于您自动跟踪列表顺序的请求;这的确是一个糟糕的设计。所有中断检查所消耗的时间可用于从头开始对列表进行排序。

以下是不减损的逻辑(复制它,并扭曲以实现不减损)

跟踪相邻对的数量
x,y
,以便
x>y
,即。,
num_decreasing_pairs -= a > c
num_decreasing_pairs += a > b
num_decreasing_pairs += b > c
num_decreasing_pairs -= a > b
num_decreasing_pairs -= b > c
num_decreasing_pairs += a > c
num_decreasing_pairs -= a > b1
num_decreasing_pairs -= b1 > c
num_decreasing_pairs += a > b2
num_decreasing_pairs += b2 > c