野生前端的數據結構練習(12)貪心演算法

来源:https://www.cnblogs.com/dashnowords/archive/2018/12/06/10073306.html
-Advertisement-
Play Games

參考代碼可見: "https://github.com/dashnowords/blogs/tree/master/Structure/GreedyAlogrithm" 一.貪心演算法 屬於比較簡單的演算法,它總是會選擇當下最優解,而不去考慮單次遞歸時是否會對未來造成影響,也就是說不考慮得到的解是否是 ...


參考代碼可見:https://github.com/dashnowords/blogs/tree/master/Structure/GreedyAlogrithm

一.貪心演算法

貪心演算法屬於比較簡單的演算法,它總是會選擇當下最優解,而不去考慮單次遞歸時是否會對未來造成影響,也就是說不考慮得到的解是否是全局最優。在很多實際問題中,尋找全局最優解的代價是非常大的,這時候就可以通過求次優解來解決問題,這種思想其實在軟體工程中很常見,例如React中著名的DOM Diff演算法中需要對比兩棵DOM樹,樹的完全對比時間複雜度為O(n^3),而React團隊通過只比較同層節點的策略將問題簡化為O(n),也就是說得到的結果從全局角度來說並不一定是絕對最優的,但是它可以在大多數情況下表現並不差。

下麵通過幾個簡單例子來理解貪心演算法(題目來自《數據結構與演算法Javascript描述》一書)。

二.貪心演算法求解背包問題

貪心演算法求解背包問題實際上很像人工求解,如果你是一個大盜,自己帶著背包在寶庫挑東西,總不能拿一張草稿紙出來開始動態規劃或手動遞歸吧,那等你求出結果來估計警察也來了,可能的做法例如:

  1. 不做衡量,拿起什麼放什麼,放不進去或者沒有更多東西了,然後離開。
  2. 從最貴的開始挑,能放進去就放,放不進去就接著挑別的,最後背包塞不下更多或者沒東西了,然後離開。
  3. 簡單計算一下性價比(一般可以以【價值】/【體積】來衡量),然後按性價比從高到低開始挑,能放進去就放,放不進去就下一個,最後背包塞不下更多或者沒東西了,離開。

這幾種方式都可以作為貪心演算法的一部分參與計算,得到的結果也不一定是一樣的,但都可以認為是一種局部最優解,同時也可能是全局最優解。

示例演算法實現:

/**
 * 貪心演算法求解背包問題局部最優解
 */
function ksack(values, weights, capacity, n) {
    var load = 0;
    var i =0;
    var w = 0;
    while (load < capacity && i < n){
        if(weights[i] <= (capacity-load)){
            w += values[i];
            load += weights[i];
        }else{
            var r = (capacity - load) / weights[i];
            w += r * values[i];
            load += weights[i];
        }
        i++;
    }
    return w;
}

var items = ["A","B","C","D"];
var values = [50, 140, 60 ,60];
var weights = [5, 20, 10, 12];
var n = 4;
var capacity = 30;

console.log(ksack(values,weights, capacity, n))

三.最長公共子串

書中第14章練習題1:使用暴力技巧求解最長公共子串

3.1 題解:

暴力求解公共字元串的方法,從較短的字元串整體開始找起,逐步縮小步長,例如長字元串為long_str,較短的字元串稱為short_str,假設short_str的長度為6,先查看short_str是否整個包含在long_str中,如果是則返回,如果不是,再將步長設置為5,然後查看short_str[0,5), short_str[1,6)這兩個字元串是否在long_str中,以此類推,過程和找零問題很相似。

3.2 參考代碼:

/**
 * 貪心演算法尋找公共子串
 */
function greedy_lsc(str1, str2) {
    //保證str2是長度較短的序列
    if (str1.length < str2.length) {
        let temp = str1;
        str1 = str2;
        str2 = temp;
    }
    let stepLength = str2.length;
    //從長到短枚舉
    while(stepLength >= 0){
        for(let i = 0; i <= str2.length - stepLength; i++){
            //相當於拿一個不斷縮短的尺子逐段截取來查看截取的片段是否被長字元串包含,
            //一旦找到則就是最長公共子串
            let checking = str2.slice(i, i+stepLength);
            if (contains(str1,checking)) {
                return checking;
            }
        }
        stepLength--;
    }
}

//str2是否是str1的子串
function contains(str1, str2) {
    return str1.indexOf(str2) !== -1;
}

//測試
let str1 = 'aabcdefsssefce';
let str2 = 'abssefsssse';

console.log(greedy_lsc(str1,str2));

四.找零問題

書中第14章練習題3:使用貪心演算法求解找零問題,要求不能用10美分,需要找零30美分。

4.1 題解:

書中有例題,沒什麼難度,就不展開講了,僅提供參考代碼。

4.2 參考代碼:

/**
 * 貪心演算法求解零錢問題
 * 要求:不能使用10美分
 */

function makeChange(money, coins) {
    let remain = money;
    if (remain / 25 > 0) {
        coins[2] = parseInt(remain / 25, 10);
        remain = remain - coins[2]*25;
    }
    if (remain / 5 > 0) {
        coins[1] = parseInt(remain / 5 , 10);
        remain = remain - coins[1]*5;
    }
    coins[0] = remain;
}

/**
 * 顯示結果
 */
function showChange(coins) {
   if (coins[2] > 0) {
     console.log('25美分-' + coins[2]);
   }
   if (coins[1] > 0) {
     console.log('5美分-' + coins[1]);
   }
    if (coins[0] > 0) {
     console.log('1美分-' + coins[0]);
   }
}

var origAmt = 30;
var coins = [];
makeChange(origAmt, coins);
showChange(coins);

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天使用navicat向MySQL中插入中文時,報錯: 在我自己資料庫設計之初,沒有設計好字元編碼格式的問題。 使用如下語句解決: ...
  • Redis五大數據類型 補充:常用命令 Ping ping下redis Dbsize 查看當前資料庫的key的數量 Select 1 切換到下標為1的資料庫中 Flushdb 清空當前庫key Flushall 清空全部庫key Redis鍵的操作(常用): 查看當前資料庫的所有key: Keys ...
  • 提示: 由於企業裡面做Redis開發,99%都是Linux版的運用和安裝, 幾乎不會涉及到Windows版,windows安裝只是為了學習而已了。 Windows版安裝 (1) 到https://github.com/dmajkic/redis/downloads 下去下載windows版本下的re ...
  • Redis是什麼? 是完全開源免費的,用C語言編寫的,遵守BSD協議,是一個高性能的(key/value)分散式記憶體資料庫,基於記憶體運行,並支持持久化的NoSQL資料庫,是當前最熱門的NoSql資料庫之一,也被人們稱為數據結構伺服器。 redis.io 是 redis 的官網 Redis 與其他 k ...
  • 報錯一: Attempted to transition from state `RESPONDER_INACTIVE_PRESS_IN` to `RESPONDER_ACTIVE_LONG_PRESS_IN`, which is not supported. This is most likely ...
  • 一、理解 頂點數據存儲在申請的緩衝區中,其由數據匯流排傳遞給著色器(如果是片元著色器,還須將頂點轉換成片元),再由著色器最終渲染到塗層上; 二、思路 1.設置塗層; 2.創建上下文; 3.清空緩存區; 4.創建渲染緩存區和幀緩存區; 5.開始繪製; 三、核心代碼 //最終渲染 四、效果 GitHub ...
  • 內聯: 在元素中添加style屬性添加樣式,只能作用於當前元素,不能復用。內部:在head裡面添加style標簽 可以當前頁面復用 不能多頁面復用 外部:寫在單獨的css文件裡面 通過link標簽引入,可以多頁面復用內聯優先順序最高內部和外部優先順序一樣,後執行的覆蓋前面執行的 ...
  • 1.寫一個深度克隆方法(es5)? 2. es6中let,const,var的區別是什麼? 3. 對數組[1,2,3,8,2,8]進行去重,es5或者es6方法? 4. 說說對es6中=>的理解? 5. 點擊一個按鈕,發出ajax請求,如何防止用戶在此請求方式返回之前再次點擊? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...