學會用另一種途徑去解決編程問題


   今天在俱樂部編程挑戰群中看到一個還算有趣的討論貼:一道淘汰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]的隨機數插入,其實最好的方法是用洗牌算法來實現。網上關於這方面的也很多,我就不班門弄斧了。

鏈接如下:

洗牌程序的兩種實現方法比較

 

  這篇文章里面講述的這些都是一些面試題,也許比較簡單,而本文章說些的這些方法也只是眾多方法中的一個,本文的目的在於提醒自己在編程的過程中需要注意的東西,努力多去思考,不要拘泥於一兩種方法,努力開拓自己的思維,有時候換另一種方法/途徑或是可以做得更好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM