Performance 如何使我的代码更快?
我写这段代码是为了解决问题4——ProjectEuler,但它花费了我太长的时间来给出答案 有什么窍门可以让它更快吗Performance 如何使我的代码更快?,performance,matlab,Performance,Matlab,我写这段代码是为了解决问题4——ProjectEuler,但它花费了我太长的时间来给出答案 有什么窍门可以让它更快吗 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)); Palindro
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秒
任何帮助都将不胜感激。我鼓励您查看此链接(),同时,我建议您使用“缓存/内存”功能,当您进行迭代计算时,您可以存储参数和答案,因此下次使用相同的参数时,您只需返回存储的答案,在过程中跳过一些计算 希望能有所帮助,如果您还有疑问,请告诉我。来源: 最大回文乘积
问题4 回文数字的两种读取方式相同。由两个两位数的乘积构成的最大回文是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);%//3位数字的所有组合
pr=n1(:).*n2(:);%//每种组合的乘积
de=dec2base(pr,10);%//这些乘积的十进制表达式
sm=pr这里只给出了部分答案,但使用字符串处理数字往往会导致性能大幅下降
这里有一个函数,它甚至可以在一行中执行两次
首先,通过将中间结果保存在变量中,尝试删除一个。如果这样可以节省大量时间,那么可能也值得删除另一个
以下是几年前我自己的方法。它不是那么伟大,但也许它能激励你
请注意,它确实使用了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)
一些讨论和解决方案代码
由于您正在查找最大值
回文,因此在收集了具有该间隔
的可能产品编号后,对于所有编号的每个可能的位数
,您可以迭代查找可能的最大编号。因此,使用n=3
,您将拥有从10000
到998001
的产品。因此,您可以先查找6位
数字中的最大回文数,然后查找5位
数字,依此类推。这种迭代方法的好处是,只要您拥有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
和Product2
由于迭代性质,如果系统能够在开始时处理产品计算的预处理部分,那么对于较高的n
,它必须足够有效
请描述问题,并解释代码背后的逻辑,确保检查并展示的输出您是否有机会尝试本页上发布的各种方法来解决您的问题?我们很想知道他们的表现如何!大约需要26.2秒。如果你找到一个技巧来移除字符串之间的转换(如@Luis现在删除的答案),它会减少到大约0.2秒。这是一个错误。我现在已经改正了+1对于你的答案,实际上我也使用字符串,但是一般来说,dec2base
似乎是fasterNice链接,但是它似乎没有涵盖他的代码中的主要问题。存储或缓存计算不足以完全解决OP遇到的问题。我想我们的解决方案在使用dec2base
和all
方面有相似之处,但是我认为我可以发布一个基于迭代的方法,并且还可以使用bsxfun
避免ndgrid/meshgrid
,这必须更有效。希望一切都好@当然是迪瓦卡!我应该想到bsxfun
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