野生前端的數據結構練習(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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...