Javascript高效图案打印

时间:2015-03-01 10:26:03

标签: javascript performance document.write

我想打印如下:

5 5 5 5 5
 4 4 4 4
  3 3 3
   2 2
    1
   2 2
  3 3 3
 4 4 4 4
5 5 5 5 5

我能够使用2 for循环来到模式的上半部分。

print(5);

function print(n) {
    for(i=n;i>=1;i--) {
        for(j=1;j<=i;j++) {
            console.log(i+" ");
        }
         console.log("<br>");   
    }
}

请参阅http://jsfiddle.net/5k8jLgmo/了解实时演示 将console.log更改为document.write

问题1 - 如何打印反射?我可以使用另一个类似的for循环。但是有更有效的方法吗?

问题2 - 要打印上半部分,我使用2 for循环。可以用O(n)来完成吗?

问题3 - 我如何document.write'n'空格。
例如,如果我必须打印"face book"(单词之间有3个空格) 如何完成它? 基本上它不是一个简单的document.write("face book"),但空间会根据循环的第i个值而不断变化。

4 个答案:

答案 0 :(得分:1)

带有1个JavaScript循环的解决方案,
但是Array()构造函数,.join().reverse()方法是内部循环,这意味着通常会运行得更快。

版本1到9:

function hourGlassString(n) {
    if (n<2) return '1';

    var r=[], out='', org=n, pad='';

    while (n>0) {
        pad=Array(org - n + 1).join(' ');
        r.push(pad + Array(n).join(n + ' ') + n + pad);
        n--;
    }

    out=r.join("\n");
    r.pop();
    out+="\n" + r.reverse().join("\n");

    return out;
}

console.log(hourGlassString(9));

输出:

9 9 9 9 9 9 9 9 9
 8 8 8 8 8 8 8 8 
  7 7 7 7 7 7 7  
   6 6 6 6 6 6   
    5 5 5 5 5    
     4 4 4 4     
      3 3 3      
       2 2       
        1        
       2 2       
      3 3 3      
     4 4 4 4     
    5 5 5 5 5    
   6 6 6 6 6 6   
  7 7 7 7 7 7 7  
 8 8 8 8 8 8 8 8 
9 9 9 9 9 9 9 9 9

版本高达99:

function hourGlassStringE(n) {
    if (n<2) return '1';

    var r=[], out='', org=n, pad='';

    while (n>0) {
        var s=' ';
        pad=Array(org - n + 1).join(s);
        if (n<10 && org>9) s=s + s;
        r.push(pad + Array(n).join(n + s) + n + pad);
        n--;
    }

    out=r.join("\n");
    r.pop();
    out+="\n" + r.reverse().join("\n");

    return out;
}

console.log(hourGlassStringE(13));

输出:

13 13 13 13 13 13 13 13 13 13 13 13 13
 12 12 12 12 12 12 12 12 12 12 12 12 
  11 11 11 11 11 11 11 11 11 11 11  
   10 10 10 10 10 10 10 10 10 10   
    9  9  9  9  9  9  9  9  9    
     8  8  8  8  8  8  8  8     
      7  7  7  7  7  7  7      
       6  6  6  6  6  6       
        5  5  5  5  5        
         4  4  4  4         
          3  3  3          
           2  2           
            1            
           2  2           
          3  3  3          
         4  4  4  4         
        5  5  5  5  5        
       6  6  6  6  6  6       
      7  7  7  7  7  7  7      
     8  8  8  8  8  8  8  8     
    9  9  9  9  9  9  9  9  9    
   10 10 10 10 10 10 10 10 10 10   
  11 11 11 11 11 11 11 11 11 11 11  
 12 12 12 12 12 12 12 12 12 12 12 12 
13 13 13 13 13 13 13 13 13 13 13 13 13

使用左+右填充构建;

回答第3个问题html将所有空格折叠成一个空格。要解决此问题,您可以使用&nbsp;\u2000 )或其他空格。而element.innerHTML代替document.write

答案 1 :(得分:0)

function print(n) {
    for(i=n;i>=1;i--) {
        for(j=i;j<=n;j++) document.write("&nbsp;");
        for(j=1;j<=i;j++) {
            document.write(i+" ");
        }
        document.write("<br>");   
    }
    for(i=2;i<=n;i++) {  // This needs to be n
        for(j=i;j<=n;j++) document.write("&nbsp;");
        for(j=1;j<=i;j++) {
            document.write(i+" ");
        }
        document.write("<br>");   
    }
}

答案 2 :(得分:0)

不确定效率本身,但肯定比for循环(在我眼中)的负载更清晰:

function hourglassNum(n)
{
  var num,i,j=0,k=0,str=''; 
  for(i=1; i<(n*2) ; i++, str='', j=0, k=0)
  {
    num = Math.abs(i-n)+1;
    while(j++ < n - num) str += ' ';
    while(k++ < num) str += ' '+num;
    console.log(str);
  }
}
hourglassNum(5);

它涉及循环目标数量的两倍,并通过计算循环索引与中间目标数量的差异来更改循环内的可打印数量:Math.abs(i-n)。然后我们将其加1以避免循环为4 - > 0.完成后,只需执行一些简单的while循环即可添加空格和可打印的数字。

更新:事实证明这实际上是非常好的性能。目前,您将使用现有的不完整代码和当前的其他解决方案:JSPerf test

答案 3 :(得分:0)

  

如何打印反射?

反向运行你的外环(线上的那个)。

  

我可以使用另一个类似的for循环。但是有更有效的方法吗?

如果你关心代码重复,那么使用一个函数来抽象它 - 一个只用于内部循环,或者一个用于给出方向的外部循环。

当然你可以将第一行存储在一个数组中,打印出来,.reverse()然后再打印出来,但这会导致空间效率低下。

  

要打印前半部分,我使用了2个循环。可以用O(n)来完成吗?

不,你不能在O(n)中打印n²字符。两个嵌套的循环非常精细,它们使用恒定的空间和最短的时间。