Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在几乎排序的数组中检测未排序的元素_Algorithm_Sorting - Fatal编程技术网

Algorithm 在几乎排序的数组中检测未排序的元素

Algorithm 在几乎排序的数组中检测未排序的元素,algorithm,sorting,Algorithm,Sorting,我有一组已排序的样本,但由于数据中的错误,有时会出现未排序的值。我需要检测这些值并删除它们。我将在下面展示一些示例数据集 20302122232425 30 3121 22 23 24 25 302122242526 20212223182526 20152122232425 在每种情况下,粗体斜体数字都应该删除。删除这些数字/检测这些数字的索引的算法是什么?仅检测 至少需要N-1个步骤来检查(检查每个元素和下一步),才能完成 但它是模棱两可的:在清单2中,什么是错的?30/31还是21/25

我有一组已排序的样本,但由于数据中的错误,有时会出现未排序的值。我需要检测这些值并删除它们。我将在下面展示一些示例数据集

20302122232425

30 3121 22 23 24 25

302122242526

20212223182526

20152122232425


在每种情况下,粗体斜体数字都应该删除。删除这些数字/检测这些数字的索引的算法是什么?

仅检测

至少需要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;//将其标记为无效。如果需要,也可以将其删除
}

我的问题是,什么样的算法可以实现同样的效果。我可以解释我尝试过的一些方法,如果这有助于将数组从低索引读取到高索引(反之亦然,这几乎不重要),并抛出(或以其他方式标记)无序值