我编写这段代码来解决问题4项目的euler,但是给我答案需要很长时间。
有什么技巧可以让它更快吗?
function S=Problem4(n)
tic
Interval=10^(n-1):10^(n)-1;
[Product1,Product2]=meshgrid(Interval);
Func=@(X,Y) X*Y;
Temp=cell2mat(arrayfun(Func,Product1,Product2,'UniformOutput',false));
Palindrome=@(X) all(num2str(X)==fliplr(num2str(X)));
Temp2=unique(Temp(:));
S=max(Temp2(arrayfun(Palindrome,Temp2)));
toc
end
并且大约需要39秒。
任何帮助都将不胜感激。
答案 0 :(得分:2)
最大的回文产品
问题4回文数字两种方式相同。由两个2位数字的乘积制成的最大回文是9009 = 91×99。
找出由两个3位数字的乘积制成的最大回文。
我会给你另一种方法,而不是分析你的代码,你可能会发现它很有用。它利用了矢量化,避免了arrayfun
和匿名函数,这可能很慢:
[n1, n2] = ndgrid(100:999); %// all combinations of 3-digit numbers
pr = n1(:).*n2(:); %// product of each combination
de = dec2base(pr, 10); %// decimal expression of those products
sm = pr<1e5; %// these have 5 figures: initial digit "0" should be disregarded
pa = false(1,numel(pr)); %// this will indicate if each product is palindromic or not
pa(sm) = all(de(sm,2:end) == fliplr(de(sm,2:end)), 2); %// 5-figure palindromic
pa(~sm) = all(de(~sm,:) == fliplr(de(~sm,:)), 2); %// 6-figure palindromic
result = max(pr(pa)); %// find maximum among all products indicated by pa
通过避免重复产品,您可以节省近一半的时间,如下所示。标记了三个新行:
[n1, n2] = ndgrid(100:999); %// all combinations of 3-digit numbers
un = n1(:)<=n2(:); %// NEW
n1 = n1(un); %// NEW
n2 = n2(un); %// NEW
pr = n1(:).*n2(:); %// product of each combination
de = dec2base(pr, 10); %// decimal expression of those products
sm = pr<1e5; %// these have 5 figures: initial digit "0" should be disregarded
pa = false(1,numel(pr)); %// this will indicate if each product is palindromic or not
pa(sm) = all(de(sm,2:end) == fliplr(de(sm,2:end)), 2); %// 5-figure palindromic
pa(~sm) = all(de(~sm,:) == fliplr(de(~sm,:)), 2); %// 6-figure palindromic
result = max(pr(pa)); %// find maximum among all products indicated by pa
答案 1 :(得分:2)
这里只是部分答案,但通常会因使用字符串处理数字而导致性能大打击。
在这里你有一个功能,甚至可以在一行中完成两次!
首先尝试通过将中间结果保存在变量中来消除一个。如果这可以节省大量时间,那么也可能值得删除另一个。
这是几年前我自己的做法。它不是那么好,但也许它可以激励你。
请注意,它确实使用num2str
,但只使用一次,并且同时使用所有相关数字。在您的代码中,您使用的arrayfun
基本上在内部使用了一个循环,可能会导致多次调用num2str
。
clear
field = (100:999)'*(100:999);
field = field(:);
fieldstr = num2str(field);
idx = fieldstr(:,1) == fieldstr(:,end);
idx2 = fieldstr(:,2) == fieldstr(:,end-1);
idx3 = fieldstr(:,3) == fieldstr(:,end-2);
list = fieldstr(idx & idx2 & idx3,:);
listnum = str2num(list);
max(listnum)
答案 2 :(得分:1)
由于您正在寻找maximum
回文,因为您使用Interval
收集了可能的产品编号,number of digits
all the numbers
你可以迭代地寻找最大可能的数字。因此,使用n = 3
,您可以从10000
到998001
作为产品。因此,您可以先查找6 digit
个数字中的最大回文数,然后选择5 digits
个,依此类推。这种迭代方法的好处是,只要您拥有get out
号码,就可以 max
。这是履行讨论中承诺的代码 -
function S = problem4_try1(n)
Interval=10^(n-1):10^(n)-1; %// Define interval definition here
prods = bsxfun(@times,Interval,Interval'); %//'# Or Use: Interval'*Interval
allnums = prods(:);
numd = ceil(log10(allnums)); %// number of digits
dig = sort(unique(numd),'descend'); %// unique digits starting from highest one
for iter = 1:numel(dig)
numd_iter = dig(iter);
numd_iter_halflen = floor(numd_iter/2);
all_crit = allnums(numd==numd_iter); %//all numbers in current iteration
all_crit_dg = dec2base(all_crit,10)-'0'; %// separate digits for a 2D array
all_curit_digits_pal = all_crit(all(all_crit_dg(:,1:numd_iter_halflen) == ...
all_crit_dg(:,end:-1:end-numd_iter_halflen+1) ,2)); %// palindrome matches
%// Find the max of palindrom matches and get out
if ~isempty(all_curit_digits_pal)
S = max(all_curit_digits_pal);
return; %// *** Get Outta Here!!
end
end
关于代码本身的一些事情
bsxfun(@times,Interval,Interval')
有效地为我们提供了Temp
中的产品值,因此这必须非常高效,因为不必处理中间Product1
和{ {1}}。Product2
,因为系统可以在开始时处理产品计算的预处理部分。答案 3 :(得分:-4)
我鼓励你看到这个链接(improving matlab performance),我建议你使用“缓存/内存”功能,当你进行迭代计算时,你可以存储参数和答案,这样下次你有了相同的参数,你只需返回存储的答案,跳过过程中的一些计算。
希望它有所帮助,告诉我你是否有更多的怀疑。