做ThoughtWorks面试题的感悟

题目要求是这样的

1. 你首先说出三个不同的特殊数,要求必须是个位数,比如3、5、7。
2. 让100个学生拍成一队,然后按顺序报数。
3. 学生报数时,如果所报数字是第一个特殊数(3)的倍数,那么不能说该数字,而要说Fizz;
                如果所报数字是第二个特殊数(5)的倍数,那么要说Buzz;
                如果所报数字是第三个特殊数(7)的倍数,那么要说Whizz。
4. 学生报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,
                比如第一个特殊数和第二个特殊数的倍数,那么不能说该数字,而是要说FizzBuzz, 以此类推。
                如果同时是三个特殊数的倍数,那么要说FizzBuzzWhizz。
5. 学生报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,
                    比如本例中第一个特殊数是3,那么要报13的同学应该说Fizz。
                    如果数字中包含了第一个特殊数,那么忽略规则3和规则4,
                    比如要报35的同学只报Fizz,不报BuzzWhizz。

在工作之前就很喜欢没事去学校的ACM网站刷题玩,现在工作后很少在做这种有意思的题目了,这次无意间看到ThoughtWorks的这道面试题,瞬间又找回了当初刷题时的感觉。

我是一名android程序员,尽管已经有一年多没有碰C语言了,但是看到这个题目的时候,第一反应还是用C语言去实现,毕竟当初的算法题目都是用C语言去实现的。

以下是我第一遍写的代码(这种C不像C,java不像java的代码风格,还希望大家不要吐槽,长时间没有用C语言了):

#include<stdio.h>
int main(void)
{
    int a,b,c;
    int i;
    //因为报数不可能报0,所以此处忽略对0的检测
    printf("请输入三个数:");
    scanf("%d%d%d",&a,&b,&c);
    printf("\n");

    //比最小的数还要小不考虑
    for(i = 1; i <a;i++){
        printf("%d\n",i);
    }

    //判断
    for(i = a; i <=100; i++)
    {
        switch(checked(a,b,c,i))
        {
        case 1:
            printf("Fizz\n");
            break;
        case 2:
            printf("Buzz\n");
            break;
        case 3:
            printf("Whizz\n");
            break;
        case 0:
            checked_multiple(a,b,c,i);
            printf("\n");
            break;
        }
    }
    return 0;
}

//检测倍数
void checked_multiple(int a, int b, int c, int n)
{
    int boolean = 0;
    if (n%a == 0){
        printf("Fizz");
        boolean = 1;
    }
    if (n%b == 0){
        printf("Buzz");
        boolean = 1;
    }
    if(n%c == 0){
        printf("Whizz");
        boolean = 1;
    }
    if(!boolean){
        printf("%d",n);
    }
}

//检测与位数相同的情况
int checked(int a, int b, int c, int n)
{
    int prev;   //十位
    int next;   //个位
    if (n >10){
        prev = n/10;
        next = n%10;
    }else{
        prev = 0;
    }
    if (a == prev || a == next){
        return 1;
    }
    if (b == prev || b == next){
        return 2;
    }
    if (c == prev || c == next){
        return 3;
    }
    return 0;
}

在第一遍写完后,我最大的感想就是:我变了。

我变的不再像当初那个一心求效率,一心求代码行数的自己,现在的我,考虑的更多的是功能的模块化,与重用性。

如果是两年前的自己,一定会一个main函数,十几二十行代码,想尽一切办法的压缩代码行数去完成这个题目。

我不知道是不是因为接触到了java,是不是因为面向对象,是不是因为做了太多的项目的原因,现在的自己考虑的更多的是别人如何看懂我的代码,我的代码如何适用更多的场合。

于是,有了如下的改动(期间发现自己对题目的理解还出了些差错,第五项说的是仅考虑第一个特殊数字)

#include<stdio.h>
int main(void)
{
    int a,b,c;
    int i,j;
    //因为报数不可能报0,所以此处忽略对0的检测
    printf("请输入三个数(用逗号分隔):");
    scanf("%d,%d,%d",&a,&b,&c);
    printf("\n");

    for(i = 1; i < a; i++){
        printf("%d\n",i);
    }

    //判断
    for(i = a; i <=100; i++){
        j = 0;
         if (checked_fizz(a,i)){
            printf("Fizz");
         }else{
            j += checked_multiple2(a,i,"Fizz");
            j += checked_multiple2(b,i,"Buzz");
            j += checked_multiple2(c,i,"Whizz");
            if (!j){
                printf("%d",i);
            }
        }
        printf("\n");
    }
    return 0;
}
//检测含有第一个数字
int checked_fizz(int a, int n){
    if (n/10 == a || n%10 == a){
        return 1;
    }else{
        return 0;
    }
}
//检测倍数
int checked_multiple2(int a, int n,char* str){
    if (n%a == 0){
        printf("%s",str);
        return 1;
    }else{
        return 0;
    }
}

我 不敢保证这是效率最高的代码,但我敢保证这是可以让任何人使用的代码,即使题目的条件改变:比如输出的文字变成kkkk,或者jjj,再或者其他的东西, 我的函数模块是不需要改变的,我的逻辑判断是不需要改变的。即使题目再多添加特殊数字,我的函数功能依旧不变,所需要改变的仅仅是main函数中对j值的 累加操作次数。

以上是我对于这道题的总结,也是我对于自己这两年改变的一次回顾。

我一直认为,人只有认识到自己的过去改变,才能为了未来更好的改变。


你可能感兴趣的:(算法,面试题,Thoughtworks)