《程式設計之美》學習筆記之 演算法設計中的逆向思維

2021-04-24 22:19:05 字數 788 閱讀 9167

兩個例子:

例一:找符合條件的整數

題目概述:給定正整數n,求最小的正整數m,使n*m十進位制表示中只有0和1.

著者給出多種解法。解法一在正整數範圍內窮舉m。解法二改進了解法一,在十進位制表示中只有0和1的正整數範圍內窮舉n*m,從而間接找到m。解法三再次改進解法二,在模n同餘的意義下按照模n的餘數對可能的n*m進行分類,這樣,便把搜尋空間從指數複雜度降到了線性複雜度。

例二:陣列分割問題

題目概述:有乙個沒有排序,元素個數為2n的正整數陣列。要求把它分割為元素個數為n的兩個陣列,並使兩個子陣列的和最接近。

假設陣列a[1..2n]所有元素的和是sum。模仿動態規劃解0-1揹包問題的策略,令s(k, i)表示前k個元素中任意i個元素的和的集合。顯然:

s(k, 1) =

s(k, k) =

s(k, i) = s(k-1, i) u

按照這個遞推公式來計算,最後找出集合s(2n, n)中與sum最接近的那個和,這便是答案。這個演算法的時間複雜度是o(22n).

因為這個過程中只關注和不大於sum/2的那個子陣列的和。所以集合中重複的和以及大於sum/2的和都是沒有意義的。把這些沒有意義的和剔除掉,剩下的有意義的和的個數最多就是sum/2個。所以,我們不需要記錄s(2n,n)中都有哪些和,只需要從sum/2到1遍歷一次,逐個詢問這個值是不是在s(2n,n)中出現,第乙個出現的值就是答案。我們的程式不需要按照上述遞推公式計算每個集合,只需要為每個集合設乙個標誌陣列,標記sum/2到1這個區間中的哪些值可以被計算出來。關鍵**如下:

以上兩例中的技術都是搜尋時非常有用的技術。

《程式設計之美》學習筆記 2 4 1的數目

一 問題 給定乙個十進位制正整數n,統計從1開始,到n 含n 的所有整數中出現的所有 1 包含各個位 的個數。二 解法 版本一 最簡單的思路,就是從1到n進行遍歷,統計逐個數上 1 的個數並相加,最後的結果就是所求的值。9 include 10 include 11 12 typedef int t...

設計原則之美學習筆記 設計原則

乙個類只負責完成乙個職責或者功能。不要設計大而全的類,要設計粒度小 功能單一的類。單一職責原則是為了實現 高內聚 低耦合,提高 的復用性 可讀性 可維護性。不同的應用場景 不同階段的需求背景 不同的業務層面,對同乙個類的職責是否單一,可能會有不同的判定結果。實際上,一些側面的判斷指標更具有指導意義和...

程式設計之美學習筆記 2 3尋找發帖水王

題意即找出陣列中超過一半的數。最直接的方法是對所有id排序,然後再掃瞄一遍排好的id列表,統計各個id出現的次數,若某個id次數超過總數的一半則輸出這個id,這個演算法的時間複雜度為o n log2n n 但事實上,若id列表有序,不必再次掃瞄列表。若乙個id出現的次數超過總數n的一半,那麼這個有序...