貪心算法:簡單而高效的求解策略C++

貪心算法詳解及C++實現

1. 什么是貪心算法

貪心算法(Greedy Algorithm)是一種在每一步選擇中都采取在當前狀態下最好或最優(即最有利)的選擇,從而希望導致結果是全局最好或最優的算法策略。

貪心算法與動態規劃不同在于它對每個子問題的解決方案都做出選擇,不能回退。動態規劃則會保存以前的運算結果,并根據以前的結果對當前進行選擇,有回退功能。

2. 貪心算法的基本要素

貪心算法適用的問題通常具有以下兩個性質:

  1. 貪心選擇性質:所求問題的整體最優解可以通過一系列局部最優的選擇來達到。
  2. 最優子結構:問題的最優解包含其子問題的最優解。

3. 貪心算法的基本步驟

  1. 建立數學模型來描述問題
  2. 把求解的問題分成若干個子問題
  3. 對每個子問題求解,得到子問題的局部最優解
  4. 把子問題的解合并成原問題的一個解

4. 經典貪心算法問題

4.1 找零錢問題

問題描述:假設有不同面額的硬幣 coins = [1, 2, 5, 10, 20, 50, 100],我們需要用最少數量的硬幣來找零 n 元。

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;vector<int> coinChange(int amount, vector<int>& coins) {sort(coins.rbegin(), coins.rend()); // 從大到小排序vector<int> result;for (int coin : coins) {while (amount >= coin) {amount -= coin;result.push_back(coin);}}if (amount != 0) {cout << "無法正好找零" << endl;return {};}return result;
}int main() {vector<int> coins = {1, 2, 5, 10, 20, 50, 100};int amount = 93;vector<int> result = coinChange(amount, coins);cout << "找零" << amount << "元需要的硬幣為:";for (int coin : result) {cout << coin << " ";}cout << endl;return 0;
}

4.2 活動選擇問題

問題描述:給定一組活動,每個活動都有一個開始時間和結束時間,選擇最大的互不沖突的活動集合。

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;struct Activity {int start;int end;
};bool compareActivity(Activity a, Activity b) {return a.end < b.end;
}vector<Activity> selectActivities(vector<Activity>& activities) {sort(activities.begin(), activities.end(), compareActivity);vector<Activity> selected;selected.push_back(activities[0]);int lastEnd = activities[0].end;for (int i = 1; i < activities.size(); i++) {if (activities[i].start >= lastEnd) {selected.push_back(activities[i]);lastEnd = activities[i].end;}}return selected;
}int main() {vector<Activity> activities = {{1, 4}, {3, 5}, {0, 6}, {5, 7},{3, 8}, {5, 9}, {6, 10}, {8, 11},{8, 12}, {2, 13}, {12, 14}};vector<Activity> result = selectActivities(activities);cout << "選擇的活動序列為:" << endl;for (Activity act : result) {cout << "[" << act.start << ", " << act.end << "] ";}cout << endl;return 0;
}

4.3 霍夫曼編碼

問題描述:霍夫曼編碼是一種用于無損數據壓縮的貪心算法,通過給出現頻率高的字符較短的編碼,出現頻率低的字符較長的編碼,來達到壓縮數據的目的。

#include <iostream>
#include <queue>
#include <unordered_map>
#include <string>using namespace std;struct HuffmanNode {char ch;int freq;HuffmanNode *left, *right;HuffmanNode(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {}
};struct compare {bool operator()(HuffmanNode* l, HuffmanNode* r) {return l->freq > r->freq;}
};void encode(HuffmanNode* root, string str, unordered_map<char, string> &huffmanCode) {if (root == nullptr) return;if (!root->left && !root->right) {huffmanCode[root->ch] = str;}encode(root->left, str + "0", huffmanCode);encode(root->right, str + "1", huffmanCode);
}void buildHuffmanTree(string text) {unordered_map<char, int> freq;for (char ch : text) {freq[ch]++;}priority_queue<HuffmanNode*, vector<HuffmanNode*>, compare> pq;for (auto pair : freq) {pq.push(new HuffmanNode(pair.first, pair.second));}while (pq.size() != 1) {HuffmanNode *left = pq.top(); pq.pop();HuffmanNode *right = pq.top(); pq.pop();int sum = left->freq + right->freq;HuffmanNode *node = new HuffmanNode('\0', sum);node->left = left;node->right = right;pq.push(node);}HuffmanNode* root = pq.top();unordered_map<char, string> huffmanCode;encode(root, "", huffmanCode);cout << "霍夫曼編碼表:" << endl;for (auto pair : huffmanCode) {cout << pair.first << " : " << pair.second << endl;}string encodedStr;for (char ch : text) {encodedStr += huffmanCode[ch];}cout << "編碼后的字符串:" << encodedStr << endl;
}int main() {string text = "hello world";cout << "原始字符串:" << text << endl;buildHuffmanTree(text);return 0;
}

5. 貪心算法的優缺點

優點:

  1. 簡單易懂,容易實現
  2. 運行效率高,時間復雜度通常較低
  3. 可以作為其他算法的輔助算法

缺點:

  1. 不能保證得到全局最優解
  2. 適用范圍有限,只有部分問題能用貪心算法解決
  3. 需要證明其正確性,有時證明較復雜

6. 貪心算法的應用場景

  1. 最小生成樹(Prim和Kruskal算法)
  2. 最短路徑問題(Dijkstra算法)
  3. 數據壓縮(霍夫曼編碼)
  4. 任務調度問題
  5. 集合覆蓋問題

7. 總結

貪心算法是一種簡單而有效的算法設計技術,適用于具有貪心選擇性質和最優子結構的問題。雖然它不能解決所有優化問題,但在適用的情況下,它通常能提供高效且簡單的解決方案。理解貪心算法的原理和應用場景,對于算法學習和問題解決能力的提升都有很大幫助。

在實際應用中,我們需要仔細分析問題是否適合使用貪心算法,并驗證其正確性。當貪心算法不能得到全局最優解時,可能需要考慮動態規劃等其他方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88128.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88128.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88128.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IDEA 中使用 <jsp:useBean>動作指令時,class屬性引用無效

問題&#xff1a;在 IDEA 中創建 Java Web項目&#xff0c;在src/model包下存在一個Student類該類中包含&#xff1a;全參構造器、私有屬性的get/set方法。然后在 jsp 頁面中使用 <jsp:useBean>創建Student類的對象&#xff1a;訪問頁面時報錯&#xff1a;原因&#xff1…

【網絡】Linux 內核優化實戰 - net.core.flow_limit_table_len

目錄參數作用查看與修改調優建議相關警告net.core.flow_limit_table_len 是 Linux 內核中的一個網絡參數&#xff0c;用于控制**流限制表&#xff08;Flow Limit Table&#xff09;**的大小。這個表主要用于限制網絡流量中單個"流"&#xff08;通常指來自同一源IP、端…

前端開發常見問題技術文章大綱

前端開發常見問題技術文章大綱 常見性能優化問題 頁面加載速度慢的原因及解決方案渲染阻塞資源的優化方法內存泄漏的檢測與修復 跨瀏覽器兼容性問題 不同瀏覽器對CSS和JavaScript的支持差異Polyfill和Shim的使用場景如何利用工具檢測兼容性問題 響應式設計挑戰 媒體查詢的最佳實…

Redis常見性能問題和解決方案有哪些?

Redis 作為高性能的內存數據庫&#xff0c;在實際使用中可能會遇到性能問題。以下是常見的性能問題及其解決方案&#xff0c;用中文總結如下&#xff1a; 1. 高延遲問題 問題描述&#xff1a;客戶端請求響應時間過長&#xff0c;可能由于網絡、命令復雜度或服務器負載導致。 解…

閃測儀應用案例丨手機中框如何突破「尺寸檢測」瓶頸?

越來越多的手機中框&#xff0c;正改為更復雜的鏤空設計&#xff0c;這種設計不僅保持了手機中框的結構強度&#xff0c;還進一步減輕了機身重量&#xff0c;同時提升了散熱性能。這讓手機中框的自動化生產增加了很多難點&#xff0c;其中的尺寸檢測就遇到了許多瓶頸。? 尺寸精…

【字節跳動】數據挖掘面試題0011:介紹下時間序列分析常用知識點

文章大綱時間序列分析全面解析一、時間序列分析的基本概念二、時間序列分析的主要方法1. 描述性分析2.統計分析方法3.預測模型&#xff08;1&#xff09;傳統統計模型&#xff08;2&#xff09;現代機器學習模型三、時間序列分析的應用場景四、模型評估五、在字節跳動的應用場景…

ubuntu中交叉編譯iperf3到目標平臺xilinx

注&#xff1a;此文為ubuntu x86系統編譯程序到xilinx aarch64系統中。 一、工具準備 x86上編譯aarch64的編譯器 sudo apt install gcc-aarch64-linux-gnu g-aarch64-linux-gnu #保證編譯器在環境變量中&#xff0c;嘗試執行aarch64-linux-gnu-gcc 目標平臺的根文件系統rootf…

Java-數據結構-集合框架

什么是集合框架集合本質是java所實現的一組數據結構&#xff0c;提供了不同的增刪改查方法。集合就是定義了接口&#xff0c;再通過不同的類去實現定義的接口&#xff0c;這些實現了接口的類就是集合類&#xff0c;例如list&#xff0c;stack&#xff0c;map。集合框架的重要性…

黑馬點評系列問題之基礎篇16jedis redis依賴引入后仍然還是報錯

問題描述依賴已經導入進去了&#xff0c;在倉庫里有***.jar和***.pom這兩個文件&#xff0c;但是點開右面的maven還是有很多爆紅。點擊maven里的更新還是不行。解決點到配置文件pom.xml在lombok這個依賴的代碼下面&#xff0c;添加上版本號&#xff0c;刷新一下右鍵單擊pom.xml…

SQL 一鍵轉 GORM 模型,支持字段注釋、類型映射、tag 自定義!

SQL 一鍵轉 GORM 模型&#xff0c;支持字段注釋、類型映射、tag 自定義&#xff01; 在使用 Golang GORM 開發項目時&#xff0c;你是否也經歷過這些「重復性痛苦」&#xff1a; ? 拿到建表 SQL&#xff0c;要手動寫 struct? 字段多、類型復雜&#xff0c;還要寫 json、go…

前端計算機視覺:使用 OpenCV.js 在瀏覽器中實現圖像處理

一、OpenCV.js 簡介與環境搭建OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一個強大的計算機視覺庫&#xff0c;廣泛應用于圖像和視頻處理領域。傳統上&#xff0c;OpenCV 主要在后端使用 Python 或 C 等語言。但隨著 WebAssembly (Wasm) 技術的發展&…

開發在線商店:基于Vue2+ElementUI的電商平臺前端實踐

Hi&#xff0c;我是布蘭妮甜 &#xff01;在當今數字化時代&#xff0c;電子商務已成為商業領域的重要組成部分。開發一個功能完善、用戶友好的在線商店應用對于企業拓展市場至關重要。本文將詳細介紹如何使用Vue2框架配合ElementUI組件庫開發一個完整的在線商店應用。 文章目錄…

vue3 隨手筆記9--組件通信方式9/2--自定義事件

一、什么是自定義事件&#xff1f; 自定義事件是 Vue 組件間通信的一種機制。子組件通過 this.$emit(事件名, 數據) 觸發一個事件。父組件監聽這個事件并執行相應的邏輯。 二、基本使用 準備工作 demo 繼續使用筆記8中的 鏈接為demo 在views文件夾下 創建新的文件夾為cust…

深入理解Reactor調試模式:Hooks.onOperatorDebug() vs ReactorDebugAgent.init()

在現代Java開發中&#xff0c;調試Reactor流是確保應用程序性能和穩定性的關鍵步驟。Reactor調試模式提供了多種初始化方法&#xff0c;其中最常用的兩種是Hooks.onOperatorDebug()和ReactorDebugAgent.init()。本文將深入探討這兩種方法的區別&#xff0c;幫助開發者選擇最適合…

QT6 源(151)模型視圖架構里的表格窗體視圖 QTableWidget 篇一:先學習倆屬性以及 public 權限的公共成員函數,

&#xff08;1&#xff09;本篇的內容因為是子類&#xff0c;內容較視圖基類簡單了一些。又因為時間緊迫&#xff0c;不再詳細舉例了。詳細的測試可以滿足好奇心&#xff0c;也可以增強寫代碼的自信心。奈何時間不夠。不完美&#xff0c;就不完美了。以后有機會&#xff0c;再補…

ffmpeg 下載、安裝、配置、基本語法、避坑指南(覆蓋 Windows、macOS、Linux 平臺)

ffmpeg 下載、安裝、配置、基本語法、避坑指南&#xff08;覆蓋 Windows、macOS、Linux 平臺&#xff09; 本文是一篇面向初學者的超詳細 FFmpeg 教程&#xff0c;包括 FFmpeg 下載、安裝、配置、基本語法 與 避坑指南。覆蓋 Windows、macOS、Linux 平臺的安裝方式與 環境變量…

Kotlin 安裝使用教程

一、Kotlin 簡介 Kotlin 是 JetBrains 開發的一種現代、靜態類型的編程語言&#xff0c;完全兼容 Java&#xff0c;主要應用于 Android 開發、后端服務開發、前端 Web 開發&#xff08;Kotlin/JS&#xff09;和多平臺開發&#xff08;Kotlin Multiplatform&#xff09;。 二、…

day08-Elasticsearch

黑馬商城作為一個電商項目&#xff0c;商品的搜索肯定是訪問頻率最高的頁面之一。目前搜索功能是基于數據庫的模糊搜索來實現的&#xff0c;存在很多問題。 首先&#xff0c;查詢效率較低。 由于數據庫模糊查詢不走索引&#xff0c;在數據量較大的時候&#xff0c;查詢性能很…

transformers 筆記:自定義模型(配置+模型+注冊為AutoCLass+本地保存加載)

Transformers 模型設計上是可定制的。每個模型的代碼都包含在 Transformers 倉庫的 model 子文件夾中&#xff08;transformers/src/transformers/models at main huggingface/transformers&#xff09;&#xff0c;每個模型文件夾通常包含&#xff1a; modeling.py&#xff1…

Java工具類,對象List提取某個屬性為List,對象List轉為對象Map其中某個屬性作為Key值

Java工具類package org.common;import lombok.extern.slf4j.Slf4j;import java.util.*; import java.util.stream.Collectors;Slf4j public final class CollectorHelper {/*** param element* param propertyName* param <E>* return*/public static <E> List toL…