学会用另一种途径去解决编程问题

   今天在俱乐部编程挑战群中看到一个还算有趣的讨论贴:一道淘汰85%面试者的百度开发者面试题 。自己一时手贱就也去做了,虽说自己也才刚毕业,但是看着那些高校的学生在大学时候就那么好学真心觉得当年大学荒废了。废话不多说就,进入正题。

1、一道淘汰85%面试者的百度开发者面试题

题目描述:

依序遍历0到100闭区间内所有的正整数,如果该数字能被3整除,则输出该数字及‘*’标记;如果该数字能被5整除,则输出该数字及‘#’标记;如果该数字既能被3整除又能被5整除,则输出该数字及‘*#’标记。

提示:

这道看似非常简单的题目,却潜藏着几个玄机。面试官通过这道题,考察学生在语法、语义、语用以及算法优化方面的能力。现实告诉我们,通过这一道题目,就可以淘汰85%的面试者。看似残酷的考察方式,却也体现出学生在基础知识、动手能力到思维能力上的差距。

需要注意的考察点:

- 语法:语法的正确书写,包括格式
- 语义:对循环、分支等语义的理解与掌握

- 语用:对变量命名、表达式及语句的组合使用

- 算法优化:如果要提高运行效率,可以在算法上寻找突破口,也可以采用空间换时间的通用原则。

  当自己看到题目的一瞬间脑海中就闪现出:for循环遍历,然后if判断,后来仔细一想,这也太简单了,肯定有坑。然后看到讨论中贴上的错误代码:

public void foo() {

     for (int i = 0; i < 100; i++) {

       if (i % 3 == 0) {

         System.out.println(i + " *");

       } else if (i % 5 == 0) {

         System.out.println(i + " #");

       } else if (i % 3 == 0 && i % 5 == 0) {

         System.out.println(i + " *#");

       }

     }

   }
View Code

  此处的错误就不多说了,缺少了3和5都能整除的那部分。自己思索以后,发现用for循环很显然次数过多,效率低下,于是便思考如何能减少循环次数。当自己再次看题目时,觉得自己被题目的第一句话“依序遍历0到100闭区间内所有的正整数”,所蒙蔽了,其实题目就是想求,在[1,100]中的3、5、15的倍数。于是茅塞顿开,其实何必for循环100次呢?

public void Foo()
        {
            Console.WriteLine("0 *#");
            for (int i = 1; i < 100 / 3 + 1; i++)
            {
                if (i * 3 <= 100)
                {
                    if (i % 5 == 0)
                    {
                        Console.WriteLine(i * 3 + " *#");
                    }
                    else
                    {
                        Console.WriteLine(i * 3 + " *");
                    }
                }
                if (i * 5 <= 100)
                {
                    if (i % 3 != 0)
                    {
                        Console.WriteLine(i * 5 + " #");
                    }
                }
            }
        }
View Code

  这段代码只需要循环34次即可,极大的提高了效率。我的思维有点偏向数学逻辑,0可以整除任何数,所以我们可以通过常识晓得他是15的倍数,应该输出“*#”。剩下的就是算出3,,5,15在[1,100]的公倍数即可。题目虽然简单,但是这种思维很重要,我们编程要做的是解决问题,所以不要在意最初的想法是什么,只要我们可以更快,更好的解决问题就好了。(PS:百度之后发的答案和我的差不多,但是更多考虑的语法、语义、语用的规范,鉴于对面要求不将答案公布以便于其他人学习探索,这里不公布官网解法了,有兴趣的同学可以去谈论区耍一下) 

2、求以下表达式的值,写出您想到的一种或几种实现方法: 1-2+3-4+……+m

  要求就是这么简单,可能好多人一看到又会开始for循环,if判断,如:

int Num =100 ;       //加到第100个数
int Sum = 0 ;
    for (int i = 0 ; i < Num + 1 ; i++)
    {
        if((i%2) == 1)
        {
            Sum += i ;
        }
        else
        {
            Sum = Sum - I ;
        }
}
System.Console.WriteLine(Sum.ToString());
System.Console.ReadLine() ;
                            
View Code

  殊不知其实我们小学就学过它的解法.

  

 int Num = 100;          //加到第100个数
Console.WriteLine(Math.Pow(-1, Num + 1) * ((Num + 1) / 2)); //-1的NUM+1次幂乘以 NUM+1整除2得到的结果
View Code

  这个例子同样简单,只为了说明在我们编程过程中,要尽量学会用数学的思维去进行解决问题,有时候会有意料之外的收获。

 

3.编写一个数组,长度为100, 然后插入[1,100]的数字 不能重复

  看到题目可能会想到的是2个for循环然后插入数据,或是用[1,100]的随机数插入,其实最好的方法是用洗牌算法来实现。网上关于这方面的也很多,我就不班门弄斧了。

链接如下:

洗牌程序的两种实现方法比较

 

  这篇文章里面讲述的这些都是一些面试题,也许比较简单,而本文章说些的这些方法也只是众多方法中的一个,本文的目的在于提醒自己在编程的过程中需要注意的东西,努力多去思考,不要拘泥于一两种方法,努力开拓自己的思维,有时候换另一种方法/途径或是可以做得更好。

posted @ 2014-04-25 00:00  写点代码换酒钱  阅读(1761)  评论(15编辑  收藏  举报