Matlab計算逆序數出現問題?

我打的代碼如下

&>&> a=4132;

&>&> b=num2str(a);

&>&> for i=1 : length(b);

d(i)=str2num(b(i))

end

&>&> init=0

&>&> for i=1 : length(b)

tmp=d(i)-d(i+1:end);

init=init+length(find(tmp&>0));

end

可是並不能計算出逆序數

本人初學者,求教


你的程序應該可以算出結果,不過你並沒有要求程序顯示結果,而且由於你的程序沒有加分號,所以最後顯示的init=0其實是循環之前那行的沒加分號的結果。

如果你想顯示最終結果需要在程序末尾加上顯示的語句,例如直接寫init不加分號,或者disp(init)等

順便說句題外話,matlab程序對於不希望顯示的行一定不要加分號,尤其是循環中的語句,因為顯示結果可以非常非常非常非常非常浪費時間。

這個問題最優演算法應該是歸併排序之類O(n log n)的演算法的,這個演算法很常見,網上代碼應該也很容易找。不過你這裡的數據很短,最優演算法不但寫起來長速度還沒什麼優勢,所以乾脆直接用暴力方法兩兩對比序列中的次序:

a = 4132;
b = int2str(a);
c = sum(sum(tril(bsxfun(@gt,b,b."))))

不過這種方法缺點也是顯然的,如果b過長需要內存很大(需要numel(b)*numel(b)大小的空間),計算量也很大

如果要求再高一些,b可能是個很長的序列,但是如果範圍很有限,例如你這裡的b的範圍只有可能對應的連續10個正整數(0到9可以對應為1到10),那麼基於這一點可以寫成更高效的暴力演算法:

b = randi(10,1,1e4); %如果是數字字元串可以減去47("0"的ascii碼減1)化為1到10的整數
n = numel(b);
c = cumsum(cumsum(accumarray({1:n,b+1},1,[n 11]),1),2,"reverse");
c = sum(c((b+1)*numel(b)+(1:numel(b))))

這樣在計算過程中產生的矩陣就是10000x11的,而非第一種方法需要的10000x10000的

而且按照這個思路,如果b中的元素有大量重複(即不同元素個數遠小於元素總個數),那可以寫成更通用的程序:

b = randi(1e3,1,1e5);
n = numel(b);
[c,~,k] = unique(b);
c = cumsum(cumsum(accumarray({1:n,k},1,[n numel(c)+1]),1),2,"reverse");
c = sum(c(k*n+(1:n)"))

這裡的cumsum(...,"reverse")需要較新的版本才有,起作用是沿反方向運算,如果版本老的話自己實現下也很容易

順便說一下,如果你要採用另一個答案裡邊的方法,那麼循環中的這句建議改一下會好很多:

total = total + sum(b(n)&>b(n+1:end));

另外,除非你知道clear和clear all的區別,且需要用clear all,否則請不要使用clear all語句。大多數情況下clear就可以滿足你的要求


「黑科技在最後」

首先,不嫌麻煩,加一層循環也不是很費事兒,當然沒你

length(find(tmp&>0))

來得清爽(矢量化).

clear all
a = 4592378612;
b = num2str(a);
total = 0;

for n = 1:length(b)
for j = n:length(b)
if str2num(b(n)) &> str2num(b(j))
total = total + 1;
end
end
end

然後,如果非要遵循標準的「矢量化」準則,你的代碼稍微改動以下也能行,你的問題在於循環的時候下標越界了.

改成下面這樣,你再試試.

clear all
a = 4132;
b = num2str(a);

for i = 1:length(b)
d(i) = str2num(b(i));
end

init = 0;
for i = 1:length(b) % i的最大值為length(b),那你的i+1必然最後會越界
tmp = d(i) - d(i:end);
init = init + sum(tmp&>0);
end

到這裡是不是感覺改得差不多,基本完事兒了?

最後就是之前承諾的「黑科技」:

你的代碼主體思路就是通過將數字轉為字元串,然後通過循環來查找每個字元(數字)後面有多小比它小的字元(數字),所以你在循環中又將字元顯式轉為數字(還是用循環操作的-_-||)實際上有更便捷的實現方法,Matlab本身是支持字元比較的,例如:

&>&>"8" &> "92361"
ans =

0 1 1 1 1

其原理就是通過ASCII編碼進行字元級的比較(逐個比較,size不匹配時自動broadcasting)

所以最後可以這樣實現:

clear all
a = 4132;
b = num2str(a);
total = 0;

for n = 1:length(b)
total = total + sum(b(n)&>b(n:end));% 這裡根據改題另一回答最初優化修正
end


推薦閱讀:

有沒有地理信息可視化的繪圖軟體?
固定效應 隨機效應 組內估計量 組間估計量 GLS的關係?
從平面圖表中提取數據的軟體?
Python對比Matlab,有什麼決定性的優勢?
如何畫有五個變數的圖形呢?

TAG:數學 | MATLAB | 機器學習 |