2014-10-07 41 views
1

我试图将一个向量分成几部分。代码要求我创建一个单独的向量当升序停止像这样:[3, 5, 9, 21, 27, 15, 10, 13]将分为三个块[3 5 9 21 27],[15][10, 13]将数组划分为块,其中每个块是最长的递增(递增)序列

我不应该使用循环,所以如果有人能够帮助我,这将是有益的。谢谢。

+0

欢迎使用stackoverflow!请考虑接受一个答案(最好回答你的问题的答案)以表明系统,你的问题解决了(左边的绿色复选标记)。 – thewaywewalk 2015-03-04 08:27:27

回答

0

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; 

我的看法是,很难避免使用循环,但是,上面的代码更加“温和”相比,发现块元素的蛮力方法有关的计算负荷按元素。

2

没有环路,一条线,我希望这是正常的;)

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 
+0

+1为一个很好的解决方案。 – 2014-10-07 19:27:46

+1

我也是+1。我总是赞成'准确的解决方案'解决方案 – rayryeng 2014-10-07 19:36:59

+0

伟大的解决方案! – 2014-10-07 22:34:28

1

它可以很容易地与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))); 
+0

同样的事情发生时,我也运行这个我也得到 [4x1双] [15] [2倍1倍] – electricsurge31 2014-10-08 01:53:15

+0

+1!并且评论让我咯咯地笑了一下。 – thewaywewalk 2014-10-08 06:01:24