2015-11-17 128 views
12

假設我得到一個奇數長度的對稱行向量,其中每個元素小於向量前半部分中的下一個元素,每個元素大於第二個元素中的下一個元素一半和中間元素是最大的。 (例如[1 2 3 2 1][10 20 50 20 10])。創建一個「金字塔」矩陣

我想創建一個矩形矩陣,其中這個行向量是它的中間行,並且等效列向量(v')是它的中間列,並且每個其他行或列是根據中間元素的給定向量的簡化版本在這一行或一列中。當沒有更多的「原始元素」時,我們把0

例子:

如果v = [1 2 3 2 1]我們得到

0 0 1 0 0 
0 1 2 1 0 
1 2 3 2 1 
0 1 2 1 0 
0 0 1 0 0 

如果v = [3 5 3]我們得到

0 3 0 
3 5 3 
0 3 0 

我做了什麼至今:我設法與v創建一個矩陣的中間行和v'作爲中間列,我寫了這段代碼:

s = length(vector); 
matrix= zeros(s); 
matrix(round(s/2),:) = vector; 
matrix(:, round(s/2)) = vector'; 

但被分配其他值卡住了。

回答

8

一個更實際的方法是產生你的矩陣作爲一個馬賽克,從一個hankel矩陣開始。出於性能方面的對比,下面是一個使用相同的格式@Divakar's solution版本:

function out=pyramid_hankel(v) 

%I suggest checking v here 
%it should be odd in length and a palindrome  

i0=ceil(length(v)/2); 
v2=v(i0:end); 

Mtmp=hankel(v2); 
out=zeros(length(v)); 
out(i0:end,i0:end)=Mtmp; 
out(1:i0-1,i0:end)=flipud(Mtmp(2:end,:)); 
out(:,1:i0-1)=fliplr(out(:,i0+1:end)); 
>> pyramid_hankel([1 2 3 2 1]) 

ans = 

    0  0  1  0  0 
    0  1  2  1  0 
    1  2  3  2  1 
    0  1  2  1  0 
    0  0  1  0  0 

對於v=[1 2 3 2 1]起始塊爲hankel([3 2 1]),這是

ans = 

    3  2  1 
    2  1  0 
    1  0  0 

從這裏應該很清楚什麼發生。

+1

@Adrian和@AndrasDeak:'hankel'函數在內部使用'bsxfun'。 – horchler

+0

哦,不要!我使用'bsxfun'的方式與使用'bsxfun.'實現'hankel'類似。AFAIK hankel有'bsxfun(@ plus')。 – Divakar

8

這裏有一個方法 -

function out = pyramid(v) 

hlen = (numel(v)+1)/2; 
updown_vec = [1:(numel(v)+1)/2 (numel(v)-1)/2:-1:1]; 
upper_part = cumsum(bsxfun(@le,(hlen:-1:1)',updown_vec)); %//' 
out = [upper_part ; flipud(upper_part(1:end-1,:))]; 
out = changem(out,v,updown_vec); 

這裏的另一種方法,有點簡單,也許 -

function out = pyramid_v2(v) 

hlen = (numel(v)+1)/2; 
updown_vec = [1:(numel(v)+1)/2 (numel(v)-1)/2:-1:1]; 
mask = bsxfun(@le,([hlen:-1:1 2:hlen])',updown_vec); %//' 
M = double(mask); 
M(hlen+1:end,:) = -1; 
out = changem(cumsum(M).*mask,v,updown_vec); 

樣品試驗 -

>> v = [1 2 3 2 1]; 
>> pyramid(v) 
ans = 
    0  0  1  0  0 
    0  1  2  1  0 
    1  2  3  2  1 
    0  1  2  1  0 
    0  0  1  0  0 
>> v = [3 5 3]; 
>> pyramid(v) 
ans = 
    0  3  0 
    3  5  3 
    0  3  0 

>> v = [99,3,78,55,78,3,99]; 
>> pyramid(v) 
ans = 
    0  0  0 99  0  0  0 
    0  0 99  3 99  0  0 
    0 99  3 78  3 99  0 
    99  3 78 55 78  3 99 
    0 99  3 78  3 99  0 
    0  0 99  3 99  0  0 
    0  0  0 99  0  0  0 
+0

雖然我的回答似乎更容易可口,你希望要麼是相當快的大問題? –

+0

由於好奇心我檢查了你的兩種計算速度的方法:@AndrasDeak - 0.055571; Divakar - 0.03777。 但是夥計們!你的mindspeed正在殺死我 - 我看到這個問題,並已經計算出所有必要的對角線的公式,並試圖實施它,揉搓我的手掌......而且你已經發布了你的答案,讓我不知道它的優雅。我仍然無法以矩陣形式開始思考,而不是以循環的形式:) –

+0

@Mikhail_Sam欣賞基準測試的努力!所以,你測試的是'_v2',對嗎?謝謝你的讚賞:) – Divakar

5

這裏的另一種方法:

v = [1 2 3 2 1]; %// symmetric, odd size 
m = (numel(v)-1)/2; 
w = [0 v(1:m+1)]; 
t = abs(-m:m); 
result = w(max(m+2-bsxfun(@plus, t, t.'),1));