用C语言编写模式的正确方法

时间:2017-05-17 10:04:01

标签: c arrays algorithm

我想获得以下输出:

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

我正在运行的代码如下:

#include <stdio.h>

int main(void) {
    int i=1,flag=0,lines=0;  //0 for forward, 1 for reverse
    while(i!=0 && lines<3){
        if(!flag){
            printf("%d ",i);
            if(i==10){
                flag=1;
                printf("\n");
                lines++;
            }
            else
                i++;
        }
        else if(flag){
            printf("%d ",i);
            if(i==1){
                lines++;
                flag=0;
                printf("\n");
            }
            else
                i--;
         }
    }
    return 0;
}

从上面的代码获得所需的输出但不确定它是否是最佳代码。还有其他方法/建议吗?考虑到无限的空间,但时间复杂度应保持最低。

条件:仅使用一个循环

7 个答案:

答案 0 :(得分:1)

使用forloops,最小化重复的代码

#include <stdio.h>

int main(void) {

    int lines, flag=1, val;

    for(lines=0;lines<3;lines++)
    {
            if(flag == 1)
                    for(val=1;val<=10;val++)
                            printf("%d ", val);
            else
                    for(val=10;val>0;val--)
                            printf("%d ", val);
            printf("\n");
            flag = -flag;
    }

    return 0;
}

答案 1 :(得分:0)

使用数组并在第一次迭代时正常迭代,反之亦然在第二次迭代中,然后再次正常迭代。

示例代码:

#include <stdio.h>

#define SIZE 10

void print_arr(int* array, int size);
void print_rev_arr(int* array, int size);

int main(void)
{
    int array[SIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int iter = 3;

    for(int i = 0; i < iter; ++i)
        if(i % 2)
            print_arr(array, SIZE);
        else
            print_rev_arr(array, SIZE);
    return 0;
}

void print_arr(int* array, int size)
{
    for(int i = 0; i < size; ++i)
        printf("%d ", array[i]);
    printf("\n");
}

void print_rev_arr(int* array, int size)
{
    for(int i = size - 1; i >= 0; --i)
        printf("%d ", array[i]);
    printf("\n");
}

输出:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c 
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
10 9 8 7 6 5 4 3 2 1 
1 2 3 4 5 6 7 8 9 10 
10 9 8 7 6 5 4 3 2 1 

答案 2 :(得分:0)

提示:您可以使用for循环向任一方向迭代:

for (int i = 1; i <= 10; ++i)

for (int i = 10; i >= 1; --i)

此外,for循环优于while,因为它真正向读者展示了#34;我正在从此迭代i。&#34;

答案 3 :(得分:0)

IO完全支配这个问题。

但迭代前进的最快方法是

for(i=0;i<N;i++)

以最快,最优雅的方式向后迭代

int i = N;
while(N--)

答案 4 :(得分:0)

你可以这样做:

  1. 使用从1开始并达到10的for循环。打印它 计数器。
  2. 使用从10开始并在1处停止的for循环。打印它 计数器。
  3. 使用从1开始并达到10的for循环。打印它 计数器。
  4. 示例代码:

    #include <stdio.h>
    
    #define LEN 10
    #define ITER 3
    
    int main(void)
    {
        for(int i = 0; i < ITER; ++i)
        {
            if(i % 2)
                for(int j = 1; j <= LEN; ++j)
                    printf("%d ", j);
            else
                for(int j = LEN; j >0; --j)
                    printf("%d ", j);
            printf("\n");
        }
        return 0;
    }
    

    输出:

    Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c 
    Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
    10 9 8 7 6 5 4 3 2 1 
    1 2 3 4 5 6 7 8 9 10 
    10 9 8 7 6 5 4 3 2 1 
    

答案 5 :(得分:0)

有两件事需要考虑。

首先是程序是否最佳。很容易证明你的程序是最优的(至少渐近最优)。您需要显示3n个数字,因此至少需要3n次迭代。你有3n次迭代,所以很好。您可能能够进一步优化迭代本身,但这将作为第二段的隐式结果出现。

第二个是可读性。您的代码有点冗长且不灵活。请考虑以下事项:

int pattern[] = {1,2,3,4,5,6,7,8,9,10};
int patternSize = sizeof(pattern)/sizeof(int);
for (int i=0; i < 3; i++)
    for (int j=0; j<patternSize; j++) {
        if (i % 2)
            printf("%d", pattern[patternSize - j - 1]);
        else
            printf("%d", pattern[i])
    }

代码更短更清晰。而且,它更具维护性。很明显你需要做些什么来促进这种模式。我可以将模式大小硬编码为10,但是当您更改模式时,这将重新引用2个更改。我可以从j的值生成模式,但这会限制可以显示的模式数量。

但是如果模式是从1到200的所有数字怎么办?我当然不会手工编写。只需用填充数组的for循环替换数组即可。您不必更改显示阵列的代码。这是关注点分离的一个小例子 - thr代码的一部分执行模式生成,另一部分执行显示,它们可以独立修改。

虽然这是渐近最优的,但可以进行优化。例如,使用该数组存储模式不如从j生成模式那样有效。但在实践中,除非需要更高的效率,否则这种方法的优势超过了小的性能损失。

答案 6 :(得分:0)

好的,这是我的看法,我认为它比大多数人更愉快:

#include <stdio.h>

int main(void)
{
    for (int i = 0; i < 3; ++i)
    {
        for (int j = 0; j < 10; ++j)
        {
            const int v = (i % 2) ? 10 - j : j + 1;
            printf("%d ", v);
        }
        putchar('\n');
    }
    return 0;
}

有些观点:

  • 不使用数组,而只是从行号(i)和位置(j)生成非常简单的模式。
  • 不适用于&#34;可插拔&#34;通过使用数组模式,因为模式非常简单和重复,这被用来简化代码。
  • 重复使用内循环,而不是重复它。
  • 在适当的位置打印换行符,实际上获得单独的行(并非所有已发布的解决方案)。

当然,将v折叠到printf()当然可以将内环的身体缩短为一条线,但我的目的是为了提高可读性和清晰度。