劍指OFFER技巧記錄

  1. 涉及單雙數問題時,可以考慮使用異或(136)
  2. 位操作求加減:
int getSum(int a, int b) {     
        while (b!=0) {
            int num = a^b;//按位y異或
            b = (unsigned int)(a&b)<<1;//按位進位
            a = num;
        }
        return a;
    }
  1. 判斷循環鏈表的方法:walker-runner法。
    就是說通過一個慢指針和一個快指針同時出發,如果兩者在某一時刻相遇,且均不爲NULL,則該鏈表是循環的。
    此時將快指針再次從頭結點出發,速度和慢節點持平,再次和慢指針相遇時就是環的入口。

  2. 從低到高不方便操作時,換個思考方式,從高到低排。

  3. n = (n-1)&n 結果是讓n最右邊的1變成0

  4. 實現數值的整數次方。需要考慮的因素:底數爲0,指數爲0或負數。
    數值的整數次方

  5. 調整數組使奇數位於前偶數位於後。
    雙指針,重點是可擴展的版本 奇偶對調

  6. 倒數第K個節點
    雙指針,考慮代碼的robust。輸入頭結點是否爲空?循環中途是否會指向空(即,K比整個鏈表的長度還長)?輸入K是否合法(K==0)?

  7. 剪繩子問題中,需要注意,繩子小端長度爲3時,最優,其次長度爲2,最後長度爲1。剪繩子

  8. 數組中的衆數
    摩爾投票,總是認爲當前數爲衆數,遇到和當前不同的數就票數-1。因爲衆數是超過數組一般以上的數,因此最後留下來的總是正確的結果。

  9. 數字序列中某一位的數字
    這類題的共性:劃分開不同位數去處理,1-9有9個數,10-99有90個數,100-999有900個數…
    數字序列中某一位的數字

  10. 1~n整數中1出現的次數
    把問題切分爲小問題解決。累加個位,十位,百位…每位上出現1的數量。詳細見代碼。
    舉例:
    對於102分別有三種情況:

    1. 個位數是2,大於1:統計從[00-10]所有個位上有1的情況,共11種。
    2. 十位數是0,小於1:統計從[0]上所有十位是1的情況,有10種。
    3. 百位數是1,等於1: 統計百位爲1的情況,取決於後面的值,爲2+1種。

    共計24種。
    1~n整數中1出現的次數

  11. 醜數
    動態規劃,第n個醜數一定存在於乘上2,3,5後比target前一個醜數要大的數中,動態規劃可解決。
    醜數

  12. 數組中的逆序對
    用到了歸併排序的思想。通過判斷左子序列能夠一次性判斷許多情況。

  13. 圓圈中最後剩下的數字
    我們將上述問題建模爲函數 f(n, m),該函數的返回值爲最終留下的元素的序號。

    首先,長度爲 n 的序列會先刪除第 m % n 個元素,然後剩下一個長度爲 n - 1 的序列。那麼,我們可以遞歸地求解 f(n - 1, m),就可以知道對於剩下的 n - 1 個元素,最終會留下第幾個元素,我們設答案爲 x = f(n - 1, m)。

    由於我們刪除了第 m % n 個元素,將序列的長度變爲 n - 1。當我們知道了 f(n - 1, m) 對應的答案 x 之後,我們也就可以知道,長度爲 n 的序列最後一個刪除的元素,應當是從 m % n 開始數的第 x 個元素。因此有 f(n, m) = (m % n + x) % n = (m + x) % n。

    圓圈中最後剩下的數字

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章