初級演算法剖析 計算字串需要的哈夫曼長度

2021-08-03 05:57:13 字數 1299 閱讀 2777

演算法要求和答案並不複雜,不複製,不直接貼結果,而是加一些個人分析,面向非演算法專業的人員。

背景:哈夫曼編碼,構造乙個二叉樹,左支代表編碼0,右支1,從根節點到葉子節點就是編碼,這樣每個樹葉節點都是具有唯一不等長編碼的,通用用於無失真壓縮。為了合理利用空間,頻率趙越高的,越要短,靠近根。每個元素有乙個相應的權重,將子節點的權重加和,就表示這一支的總權重。自然權重越小,越要靠底層。所以,構建過程是:取權重最小的2個元素,形成樹,根是權重和。將根放回剩餘元素,迭代這個過程。細節不再解釋。由於解析編碼是從根開始的,這使的乙個連續的編碼,有固定的解析路徑,也是就唯一的結果。

要求:計算乙個字串需要的編碼長度,編碼權重是單詞各字母的單詞內出現頻率。

技巧:初步想法自然是先構建哈夫曼樹,然後計算出每個字母的長度,相加即可。但是,由於頻率並不是全域性統計出來,而是相對單詞,所有節點路徑都走且只走一遍,長度和剛好等價於權值和,結果實際是所有葉子節點的路徑,不含根,也可以理解為含根不含 葉子,葉子和根分別是路徑的兩端,加和等值,計算編碼時, 高度比層次少1,所以要減去一邊。用佇列處理的話,不計根更方便。舉例如下:

字串:1123,1頻率是2,2、3是1,所以,哈夫曼樹如下,1的編碼是:0,頻率最高也是短,2、3是10,11,總編碼是001011

不含葉節點的話,1高度1,佔2位,可以理解為加了一次1的權重。2、3各佔1位,高度2 ,可以理解為加1次。由於根和葉總和等值,所以思路設計為:

優先佇列取小值,放入所有葉節點,即單詞字母統計,每齣2個,加和放回去,直到佇列不足2個,丟棄根節點。這個思路設計,使長度是1時,要單獨返回根節點。

下圖中,圓圈上的都是權重,外面的紅色是數字字元:

**如下:

int gethflen(string s) override

cout << vectostr(c_size, ' ') << endl;

priority_queue, greater> q;

for(size_t i = 0; i < c_size.size(); i++)

if(q.size() == 1)       //只有1個節點情況

return q.top();

int sum = 0;            //初值0,涵蓋了空串情況

while(q.size()>1)

return sum;

}

演算法:個人認為,前期靠智商,聰明就行。中後期要靠經驗了,不然智商再好,也是在重走科研路線,耗不起,要基於別人的成果向前。

LeetCode 初級演算法 字串

1.用的是遞迴方法,要注意邊界處理 2.比如n 4,則n 3時的序列稱為n 4的pre序列,用pre序列來 下乙個序列,也就是要對pre序列進行遍歷,對pre遍歷的過程中,因為用的是index和index 1進行對比,要設定乙個溢位的處理。public string countandsay int ...

LeetCode 反轉字串 初級演算法

題目 請編寫乙個函式,其功能是將輸入的字串反轉過來。示例 輸入 s hello 返回 olleh 思路 這個題感覺就是老生常談的題了,算是字串裡很簡單的題了,方法也比較多,我就寫幾個方法吧 第乙個 用字元指標來做,這是c裡的方法,思路很簡單,就是把原來的字串前後位置顛倒一下,交換下位置 如下 cha...

LeetCode初級演算法 字串 4

題目 有效的字母異位詞 給定兩個字串 s 和 t 編寫乙個函式來判斷 t 是否是 s 的乙個字母異位詞。示例 1 輸入 s anagram t nagaram 輸出 true 示例 2 輸入 s rat t car 輸出 false 說明 你可以假設字串只包含小寫字母。高階 如果輸入字串包含 uni...