Algorithm 在几乎排序的数组中检测未排序的元素
我有一组已排序的样本,但由于数据中的错误,有时会出现未排序的值。我需要检测这些值并删除它们。我将在下面展示一些示例数据集 20302122232425 30 3121 22 23 24 25 302122242526 20212223182526 20152122232425Algorithm 在几乎排序的数组中检测未排序的元素,algorithm,sorting,Algorithm,Sorting,我有一组已排序的样本,但由于数据中的错误,有时会出现未排序的值。我需要检测这些值并删除它们。我将在下面展示一些示例数据集 20302122232425 30 3121 22 23 24 25 302122242526 20212223182526 20152122232425 在每种情况下,粗体斜体数字都应该删除。删除这些数字/检测这些数字的索引的算法是什么?仅检测 至少需要N-1个步骤来检查(检查每个元素和下一步),才能完成 但它是模棱两可的:在清单2中,什么是错的?30/31还是21/25
在每种情况下,粗体斜体数字都应该删除。删除这些数字/检测这些数字的索引的算法是什么?仅检测 至少需要N-1个步骤来检查(检查每个元素和下一步),才能完成 但它是模棱两可的:在清单2中,什么是错的?30/31还是21/25 如果错误数字被隔离,您只需删除它们。但是如果你有,比如说,两个数字,怎么办?你必须定义更多的规则 检测和排序: 复杂性: 如果您的列表已完全排序,则需要N-1个步骤(检查每个元素并下一步)来完成 如果有一个未排序的元素,则需要logn在适当的位置替换它(如果我假设所有其他元素都已排序,并且在类似二叉树的特殊结构中) 如果有k个未排序的元素,则需要k个logn So N(检查)+k日志N(插入) 如果所有东西都被弄乱了,那么N log N,这是排序的经典复杂性 算法: 所以,最简单的算法是在平衡树中迭代,并在适当的位置插入。这是一种插入排序
它与smoothsort类似:检测相对简单,所需步骤较少-您可以在
O(n)
时间内完成。只需迭代数组并将每个元素与下一个元素进行比较。您将能够从序列号中找到(并标记索引或丢弃)
然而,您的第二个案例使这成为一个问题。我假设您总是希望保留数字列表中最长的递增子序列(如第二种情况)
使用数组和二进制搜索可以有效地解决这个问题。该算法对每个序列元素执行单个二进制搜索,其总时间可以表示为O(n logn)
按顺序处理序列元素,保持迄今为止发现的最长递增子序列。将序列值表示为X[0],X[1]
等。L
表示迄今为止发现的最长递增子序列的长度
M[j]
存储最小值X[k]
的索引k
,以便在k范围内有一个长度j
不断增加的子序列≤ 我
<代码>j≤ K≤ 我总是这样P[k]
在以X[k]
结尾的最长递增子序列中存储X[k]
序列X[M[1]]、X[M[2]]、…、X[M[L]
在算法的所有点上都是不变的
P = array of length N
M = array of length N + 1 // Using a 1 indexed array for ease of understanding
L = 0
for i in range 0 to N-1:
// Binary search
lo = 1
hi = L
while lo ≤ hi:
mid = ceil((lo+hi)/2)
if X[M[mid]] < X[i]:
lo = mid+1
else:
hi = mid-1
newL = lo
P[i] = M[newL-1]
M[newL] = i
if newL > L:
L = newL
S = array of length L
k = M[L]
for i in range L-1 to 0:
S[i] = X[k]
k = P[k]
return S
P=长度为N的数组
M=长度为N+1//的数组,为便于理解,使用1索引数组
L=0
对于0到N-1范围内的i:
//二进制搜索
lo=1
hi=L
而罗≤ 你好:
中=天花板((低+高)/2)
如果X[M[mid]]L:
L=newL
S=长度为L的数组
k=M[L]
对于L-1至0范围内的i:
S[i]=X[k]
k=P[k]
返回S
可以在上找到用于此的伪代码
如果您确实想在列表中保留无序元素,只需使用插入排序对数组进行排序。我认为这应该适合您。它找到最长的子序列,然后清除其他元素。实现是用c语言实现的#
publicstaticvoidmain(){
int[][]数据列表={
新[{20,30,21,22,23,24,25},
新[{30,31,21,22,23,24,25},
新[{30,21,22,23,24,25,26},
新[{20,21,22,23,18,25,26},
新[]{20,15,21,22,23,24,25}
};
foreach(数据列表中的var数据)
检测并移除未排序(数据);
}
///
///采用升序数据。您也可以将其调整为降序数据
///
静态无效检测和移除未排序(ILST数据){
//第一步:找到异常值;而不是找到正确的序列
int startOfLongestSeq=0,LENOOFLONGESEQ=0;
int startOfCurrSeq=0,lenOfCurrSeq=0;
对于(int i=0;idata[i+1]){//我们打破了升序,那么这是另一个序列
lenOfCurrSeq=i——startOfCurrSeq+1;
如果(lenOfCurrSeq>LenofLongsSeq){
LenOfLongSeq=lenOfCurrSeq;
startOfLongestSeq=startOfCurrSeq;
}
startOfCurrSeq=i+1;
}
}
lenOfCurrSeq=data.Count-startOfCurrSeq;
如果(lenOfCurrSeq>LenofLongsSeq){
LenOfLongSeq=lenOfCurrSeq;
startOfLongestSeq=startOfCurrSeq;
}
//第二步:清除异常值
//现在我们知道哪个序列是最大的
//我们应该去掉其他的序列
对于(int i=startOfLongestSeq-1;i>=0;--i)
data[i]=-1;//将其标记为无效。如果需要,也可以将其删除
对于(int i=data.Count-1;i>=startOfLongestSeq+lenOfLongestSeq;--i)
data[i]=-1;//将其标记为无效。如果需要,也可以将其删除
}
我的问题是,什么样的算法可以实现同样的效果。我可以解释我尝试过的一些方法,如果这有助于将数组从低索引读取到高索引(反之亦然,这几乎不重要),并抛出(或以其他方式标记)无序值