ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

野生前端的数据结构练习(12)贪心算法

2019-07-10 10:04:47  阅读:247  来源: 互联网

标签:12 str2 str1 coins remain 算法 数据结构 贪心


【摘要】 贪心算法求解背包问题实际上很像人工求解,如果你是一个大盗,自己带着背包在宝库挑东西,总不能拿一张草稿纸出来开始动态规划或手动递归吧,那等你求出结果来估计警察也来了。

参考代码可见: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);

来源:华为云社区  作者:大史不说话

标签:12,str2,str1,coins,remain,算法,数据结构,贪心
来源: https://blog.csdn.net/devcloud/article/details/94602103

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有