我试图将一个向量分成几部分。代码要求我创建一个单独的向量当升序停止像这样:[3, 5, 9, 21, 27, 15, 10, 13]
将分为三个块[3 5 9 21 27]
,[15]
和[10, 13]
。将数组划分为块,其中每个块是最长的递增(递增)序列
我不应该使用循环,所以如果有人能够帮助我,这将是有益的。谢谢。
我试图将一个向量分成几部分。代码要求我创建一个单独的向量当升序停止像这样:[3, 5, 9, 21, 27, 15, 10, 13]
将分为三个块[3 5 9 21 27]
,[15]
和[10, 13]
。将数组划分为块,其中每个块是最长的递增(递增)序列
我不应该使用循环,所以如果有人能够帮助我,这将是有益的。谢谢。
diff
函数计算数组中相邻元素之间的差异。在diff
结果中为负值的元素指向升序“破碎”的位置。
所以:
v = [3, 5, 9, 21, 27, 15, 10, 13];
dv = diff(v);
nb = sum(dv <= 0); % number of blocks
b = cell(1, nb); % container of blocks
ix = find(dv <= 0); % start indices of blocks
ix0 = 1;
for k = 1:nb
ix1 = ix(k);
b{k} = a(ix0:ix1);
ix0 = ix1 +1 ;
end;
我的看法是,很难避免使用循环,但是,上面的代码更加“温和”相比,发现块元素的蛮力方法有关的计算负荷按元素。
没有环路,一条线,我希望这是正常的;)
a = [3, 5, 9, 21, 27, 15, 10, 13];
output = accumarray(cumsum([0; diff(a(:))] < 0)+1, a, [], @(x) {x})
一些解释:
%// find out where the vector decreases:
da = [0; diff(a(:))]
%// and create a mask
mask = da < 0
%// sum the mask up cumulatively and add +1
subs = cumsum(mask) + 1
%// use accumarray to gather everything
output = accumarray(subs,a,[],@(x) {x})
如果有后续相同的号码,就像这里:
a = [3, 5, 9, 21, 27, 27, 15, 10, 13];
上面的解决方案计数seco第二27
第一组,如果你希望它是一个独立的组,改变面膜:
mask = da <= 0
+1为一个很好的解决方案。 – 2014-10-07 19:27:46
我也是+1。我总是赞成'准确的解决方案'解决方案 – rayryeng 2014-10-07 19:36:59
伟大的解决方案! – 2014-10-07 22:34:28
它可以很容易地与mat2cell
来完成:
x = find(diff(a)<0);
result = mat2cell(a, 1, [x(1) diff(x) numel(a)-x(end)]);
如果你想要一个-liner:
result = mat2cell(a, 1, diff(find(diff([inf a -inf])<0)));
同样的事情发生时,我也运行这个我也得到 [4x1双] [15] [2倍1倍] – electricsurge31 2014-10-08 01:53:15
+1!并且评论让我咯咯地笑了一下。 – thewaywewalk 2014-10-08 06:01:24
欢迎使用stackoverflow!请考虑接受一个答案(最好回答你的问题的答案)以表明系统,你的问题解决了(左边的绿色复选标记)。 – thewaywewalk 2015-03-04 08:27:27