给定像[15, 14, 12, 3, 10, 4, 2, 1]
这样的数组。如何确定哪些元素出现故障并将其删除(本例中为数字3)。我不想对列表进行排序,但会检测异常值并将其删除。
另一个例子:
[13, 12, 4, 9, 8, 6, 7, 3, 2]
我希望能够删除#4和#7,以便我最终得到:
[13, 12, 9, 8, 6, 3, 2]
当您遇到这种情况时,也会出现问题:
[15, 13, 12, 7, 10, 5, 4, 3]
您可以删除7或10以使此数组排序。
一般来说,我试图解决的问题是给出一个数字读数列表(有些可能会被关闭很多)。我希望数组只包含遵循一般趋势线的值并删除任何异常值。我只是想知道是否有一种简单的方法可以做到这一点。
答案 0 :(得分:3)
higuaro描述的一个简单算法可以帮助您生成正确的序列:
对于索引为i
的每个元素,如果a[i] < a[i + 1]
,我们只需删除该元素a[i]
。
for(int i = 0; i < size; i++)
while(a[i] < a[i + 1]){
remove a[i];
i--;
}
但是,这种方法不能保证删除元素的数量最少。例如,对于此序列[10,9,8,100,1,0],删除100将是最佳的,而不是删除8,然后是9,然后是10。
要找到要删除的最小元素数,我们注意到我们需要找到最长的递减子序列,这类似于其解决方案已经描述的经典longest increasing sub sequence here
答案 1 :(得分:3)
我会将你的问题减少到最长的(减少的)子序列问题。
https://en.wikipedia.org/wiki/Longest_increasing_subsequence
由于您的序列接近排序,因此您可以保证获得满意的结果(即整齐地跟随趋势线)。
有许多解决方案;其中一个是在免费书中描绘的,Fundamentals of Computer Programming with C#&#34;作者:Svetlin Nakov和Veselin Kolev;问题见第257页,练习6;解决方案在第260页。
取自本书:
编写一个程序,它在数组arr [n]中找到增加元素的最大序列。没有必要连续放置元素。例如:{9,6,2,7,4,7,5,5,8,4} - &gt; {2,4,6,8}。
解决方案:
我们可以用两个嵌套循环和另一个数组len [0 ... n-1]来解决这个问题。在数组len [i]中,我们可以保持最长的连续增加序列的长度,该序列从数组中的某处开始(确切地说无关紧要)并以元素arr [i]结束。因此len [0] = 1,len [x]是最大和max(1 + len [prev]),其中prev&lt; x和arr [prev]&lt; ARR [X]。根据定义,我们可以用两个嵌套循环计算len [0 ... n-1]:外部循环将使用循环变量x从左到右遍历数组。内循环将从开始到位置x-1遍历数组并搜索具有最大值len [prev]的元素prev,其中arr [prev]&lt; ARR [X]。在搜索之后,我们将len [x]初始化为1 +最大找到的len [prev]值或者为1,如果找不到这样的值。
所描述的算法找到所有最大上升序列的长度,其在每个元素处结束。这些值中最大的一个是最长的序列的长度。如果我们需要找到组成最长序列的元素本身,我们可以从序列结束的元素开始(在索引x处),我们可以打印它,我们可以搜索前一个元素(prev)。根据定义prev&lt; x和len [x] = 1 + len [上一页]因此我们可以找到带有从1到x-1的for循环的prev。之后我们可以重复相同的x = prev。通过多次查找和打印前一个元素(prev)直到它存在,我们可以找到构成最长序列的元素(从最后一个到第一个)。