给定:n个离散数据点[ti,xi],它应描述单调函数(ti =时间,xi =数据)。一些点是“异常值”,或者违反单调函数规则(x {i + 1}> = x {i}用于增加,x {i + 1}< = x {i}用于递减)。
我试图找到一种算法来确定我必须消除的最小数据点数才能获得单调函数。我也知道它是增加还是减少。
我尝试使用移动中值滤波器并识别在滤波函数之上或之下的某些方差的点,但我无法识别所有点。
这个问题的最佳方法是什么?
我正在使用MATLAB,但解决方案肯定可以推广。
答案 0 :(得分:1)
这是一个使用Patience sort从给定数组中找到增长最长的子序列的解决方案。解决方案不一定是唯一的,但保证其长度大于或等于任何其他增加的子序列。如果您只想知道最长增长子序列的长度,则可以使用更简单的函数。
function subsequence = PatienceLIS(sequence)
% Use patience sort to generate a (not necessarily unique)
% longest increasing subsequence from a given sequence
subInds = []; % indices of subsequence elements
for s = 1:numel(sequence)
% put new element on first stack with top element > sequence(s)
newStack = find(sequence(s) <= [sequence(subInds) inf], 1);
subInds(newStack) = s; % put current index on top of newStack
if (newStack > 1)
% point to the index currently to the left
pred(s) = subInds(newStack - 1);
end
end
% recover the subsequence indices
% last element in subsequence is found from last subInds
pathInds = subInds(end);
while (pred(pathInds(1)) > 0)
pathInds = [pred(pathInds(1)) pathInds]; % add predecessor index to list
end
subsequence = sequence(pathInds); % recover subsequence from indices
end
示例运行:
x = [7 4 11 -1 13 12 10 8 5 14 14 12 15 6 1 3 2 9];
>> PatienceLIS(x)
ans =
4 11 12 14 15
答案 1 :(得分:0)
我想到了有限用途的递归解决方案(因为它不会导致最长的子序列),但也许
function [pts_to_remove, monoseq] = q48647287
sequence = randi(1000,1000,1,'int16');
[pts_to_remove, monoseq] = remove_pts(sequence, false, 0);
% Now we can try to setdiff different subsets of `monoseq` from `sequence` and rerun the
% algorithm. Among the results we'll take the longest `monoseq`, and repeat the procedure as
% many times as needed.
% Of course it needs to be (dis)proven mathematically whether this approach can result in
% the longest possible subsequence.
end
function [pts_removed, seq] = remove_pts(seq, shouldIncrease, rem_pts_so_far)
if shouldIncrease
d = diff([-Inf; seq]) >= 0;
else
d = diff([ Inf; seq]) <= 0;
end
to_rem = sum(~d);
if to_rem % > 0
pts_removed = remove_pts(seq(d), shouldIncrease, rem_pts_so_far + to_rem);
else
pts_removed = rem_pts_so_far;
end
end