Javascript 递归算法无法在分配的时间内完成测试
我在做一个测试,需要一个二进制层析成像算法。提供了一组38个测试值来测试正确性,但完成所有测试也有1 CPU秒的时间限制。问题如下: 如果存在m×n矩阵A,且每个元素为0或1,则输出“是”,以便 否则输出“否” 对于每个测试,提供2个阵列:Javascript 递归算法无法在分配的时间内完成测试,javascript,algorithm,performance,binary,tomography-reconstruction,Javascript,Algorithm,Performance,Binary,Tomography Reconstruction,我在做一个测试,需要一个二进制层析成像算法。提供了一组38个测试值来测试正确性,但完成所有测试也有1 CPU秒的时间限制。问题如下: 如果存在m×n矩阵A,且每个元素为0或1,则输出“是”,以便 否则输出“否” 对于每个测试,提供2个阵列: r(矩阵中每行的总和) c(矩阵中每列的总和) 在方程式中: m是r数组的长度,其中1=0;y-=1){ 行[y]=矩阵[y][x]; } 设和=0; for(设i=rows.length-1;i>=0;i-=1){ 总和+=行[i]; } a[x]=总
- m是r数组的长度,其中1=0;y-=1){
行[y]=矩阵[y][x];
}
设和=0;
for(设i=rows.length-1;i>=0;i-=1){
总和+=行[i];
}
a[x]=总和;
}
返回a;
};
常数相等=函数(a,b){
常数长度=a.长度;
如果(长度!==b.长度){
返回false;
}
for(设i=length-1;i>=0;i-=1){
如果(a[i]!==b[i]){
返回false;
}
}
返回true;
};
const addRow=函数(i、prev、r、c、result){
如果(结果){
返回结果;
}
常数n=c.长度;
常数ri=r[i];
if(ri<0 | | ri>n){
抛出新的RangeError(“ri超出范围”);
}
常数p=置换(n,ri);
常数m=r.长度;
常数rsLast=m-1;
常数nextI=i+1;
对于(设x=p.length-1;x>=0;x-=1){
常数置换=p[x];
const next=prev.slice();
下一步。推(排列);
const sums=getMatrixSum(n,next);
如果(i
=0;j-=1){ if(和[j]>c[j]){ 备忘录+=1; } } if(!memo&&addRow(nextI、next、r、c、result)){ 返回true; } }否则,如果(相等(总和,c)){ 返回true; } } 返回false; }; 常数可解=函数(r,c){ 常数m=r.长度; 常数n=c.长度; 如果(m<1 | n>1000){ 抛出新错误(“坏数据”); } 对于(设j=n;j>=0;j-=1){ 常数cj=c[j]; 如果(cj<0 | | cj>m){ 抛出新的范围错误(“cj超出范围”); } } 返回addRow(0,[],r,c,false)?“是”:“否”; }; log(可解([2,3,2],[1,1,3,2]);
log(可解([0,0,3],[0,0,3])代码>我还没有准备好进行测试,但在事件发生后我发现了一种更有效的算法“严格使用”; const sortNumber=函数(a,b){ 返回b-a; }; 常数可解=函数(r,c){ 常数m=r.长度; 常数n=c.长度; 如果(m<1 | n>1000){ 抛出新错误(“坏数据”); } 对于(设j=n;j>=0;j-=1){ 常数cj=c[j]; 如果(cj<0 | | cj>m){ 抛出新的范围错误(“cj超出范围”); } } while(r.length){ c、 排序(sortNumber); 常数ri=r.pop(); if(ri<0 | | ri>n){ 抛出新的RangeError(“ri超出范围”); } 如果(ri){ 如果(!c[ri-1]){ 返回“否”; } 对于(设j=ri-1;j>=0;j-=1){ c[j]=1; } } } 对于(设j=n-1;j>=0;j-=1){ if(c[j]){ 返回“否”; } } 返回“是”; }; log(可解([2,3,2],[1,1,3,2]);
log(可解([0,0,3],[0,0,3])代码>因为置换会屈服于暴力,所以在开发类似于此的算法时,它们应该是最后的手段。大多数情况下,它们是不需要的 正如我在上面所评论的,我有一种感觉,一种策略可能是首先将
和r
数组降序排序,然后从较大的数组开始。我还没有时间实现一个JS代码来解决这个问题,所以我还没有机会进行彻底的测试。请看一看,如果你发现一个缺陷,请提及 在下面的算法可视化表示中,我们尝试c
和r=[1,3,1,3]
c=[3,2,1,2]
表示占用的单元格,红点表示不可触及的单元格,而空单元格显然是空闲单元格。因此,在表示单元格的实数算法中,我们需要一个数据类型,如红点的X
,而{value:false,avail:false}
将意味着一个自由空间。或者,为了节省空间和速度,您可以使用一种数据类型,如红点的数据类型为{value:false,avail:true}
,自由空间的数据类型为0b00
,占用(这里的X表示不关心)单元格的数据类型为0b01
注意:值得一提的是我们处理0b1X
的步骤3。插入三个c[0]
s后,我们必须检查X
s占用的行,以更新这些行中空单元格的状态。在这种情况下,对于r[2],所有的空单元格都是不可触及的 编辑: 嗯。。好的,因为我们不需要在2D数组结构中构造解决方案,只需要回答所提供的数据是否有意义,所以我提出了另一个更简单的想法,基本上基于上述方法。我真的不认为会比这更快。它解决了一个999乘1000板在50毫秒左右 让我们开始吧X
- 输入是
然而,这里的一个重要条件是数组r=[2,3,2];c=[1,1,3,2]
和c
的总和应该是相同的。我们可以简单地在代码的开头检查它,或者不检查它,只在r
满0的情况下执行以下步骤并通过检查。下面的代码更倾向于后一种方法c
- 排序
so递减<代码>r=[3,2,2];c=[1,1,3,2]代码>r
- 尝试将
(在第一种情况下为3)将r[0]
的许多非零元素减少1。现在c
变成c
。如果失败,则不再尝试并返回[0,0,2,2]
false
- 现在我们已经完成了行
,recursivellr[0]
71634527 7 x xxxxxx 3 x x x 5 x x xx x 4 x x x x 6 x xxxx x 2 x x 8 xxxxxxxx
- 输入是