《趣学算法(第2版)》读书笔记 Part 4 :贪心算法基础(操作)

14天阅读挑战赛


系列笔记链接

《趣学算法(第2版)》读书笔记 Part 1 :如何高效学习算法

《趣学算法(第2版)》读书笔记 Part 2 :算法入门

《趣学算法(第2版)》读书笔记 Part 3 :贪心算法基础(理论)

《趣学算法(第2版)》读书笔记 Part 4 :贪心算法基础(操作)


贪心算法基础(操作)

对应图书2.2章节内容。

通过本节的学习,掌握最简单的贪心算法求解问题方法。


文章目录

    • 系列笔记链接
    • 贪心算法基础(操作)
      • 最优装载问题
      • 问题分析
      • 算法设计
      • 伪代码解析
      • 算法复杂度分析
      • 补充
    • 大佬营友们的笔记


最优装载问题

在北美洲东南部,有一片神秘的海域,那里碧海蓝天、阳光明媚,这正是传说中海盗最活跃的加勒比海(Caribbean Sea)。
有一天,海盗们截获了一艘装满各种各样古董的货船,每一件古董都价值连城,一旦打碎就失去了它的价值。虽然海盗船足够大,但载重量为 C C C ,每件古董的重量为 w i w_i wi ,海盗们该如何把尽可能多数量的宝贝装上海盗船呢?

古董重量清单如下表所示,海盗船的载重量W为30,在不打碎古董且不超出载重量的情况下,怎样才能装入最多的古董呢?

古董重量清单:

重量W[i] 4 10 7 11 3 5 14 2

问题分析

问题要求装载古董的数量尽可能多,而船的载货量是固定的,在载重量有限的情况下,优先把重量小的古董装进去,装的古董最多。
因此,采用重量最小者先装的贪心策略,从局部最优达到全局最优,从而得到最优装载问题的最优解。


算法设计

  1. 把n个古董的重量从小到大(非递减)排序。
    当载重量为定值 C C C 时, w i w_i wi 越小时,可装载的古董数量 n n n 越大。只要依次选择最小重量古董,直到不能再装为止。
  2. 按照贪心策略装入古董,直到不能装时达到最优。
    n n n 个古董按重量从从小到大(非递减)排序,然后根据贪心策略尽可能多地选出前 i i i 个古董,直到不能继续装为止,此时达到最优。

贪心策略是重量最小的古董先装,每次从余下的古董中选择一个重量最小的古董。
如果采用顺序查找法寻找最小值,则 n n n 个元素最多需要比较 n n n 次。
第1次选择时有 n n n 个古董,需要比较 n n n 次;
第2次选择时有 n − 1 n-1 n1 个古董,需要比较 n − 1 n-1 n1 次;
…;
n n n 次选择时,需要比较 1 1 1 次;
总共需要比较 n ( n + 1 ) / 2 n(n+1)/2 n(n+1)/2 次,时间复杂度为 O ( n 2 ) O(n2) O(n2) 。如果采用快速排序法寻找最小值,也就是先从小到大排序,再按顺序选择,则时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn) ,相比顺序查找法更优。
在序列没有变化(静态)的情况下,如果需要多次从序列中选择最小值或最大值,那么可以采用先排序的办法,这样效果更好。

  • 对这批古董按重量进行非递减排序,排序后的古董重量清单见下表:
重量W[i] 2 3 4 5 7 10 11 14
  • 按照贪心策略,每次选择重量最小的古董装入海盗船(tmp代表已装入的古董重量,ans代表已装入的古董数量):

    ①选择排序后的第 1 1 1 个古董,装入重量tmp=2,没有超出载重量,ans=1
    ②选择排序后的第 2 2 2 个古董,装入重量tmp=2+3=5,没有超出载重量,ans=2
    ③选择排序后的第 3 3 3 个古董,装入重量tmp=5+4=9,没有超出载重量,ans=3
    ④选择排序后的第 4 4 4 个古董,装入重量tmp=9+5=14,没有超出载重量,ans=4
    ⑤选择排序后的第 5 5 5 个古董,装入重量tmp=14+7=21,没有超出载重量,ans=5
    ⑥选择排序后的第 6 6 6 个古董,装入重量tmp=21+10=31,超出载重量,算法结束。

    由此可以看出,能够装入海盗船的古董最多为ans=5个。


伪代码解析

  1. 选择合适的数据结构
    根据前面的算法设计描述,确定用一维数组存储古董的重量:double w[N];//一维数组存储古董的重量

  2. 利用C++标准库中的排序函数sort,对古董的重量进行从小到大(非递减)排序。

使用sort排序函数需要引入头文件algorithm,语法如下:

#include`

sort 函数的语法描述如下:

sort(begin, end) //参数begin和end用于指定范围,它们分别表示排序数组的首地址和尾地址
                 //sort函数默认执行升序排序

调用 sort 函数,对古董的重量从小到大进行排序:

sort(w, w+n);
  1. 按照贪心策略找出最优解。

伪代码描述如下:

sort(w,w+n); //按古董重量升序排序
double tmp=0.0;
int ans=0; //tmp为已装载到船上的古董重量,ans为已装载的古董个数
for(int i=0;i<n;i++)
{
    tmp+=w[i];
    if(tmp<=c)
        ans++;
    else
    break;  
}

算法复杂度分析

时间复杂度
首先需要按古董重量排序,调用 sort 函数,其平均时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn) ,输入和贪心策略求解的两个 for 语句时间复杂度均为 O ( n ) O(n) O(n) ,因此时间复杂度为 O ( n + n l o g n ) O(n + nlogn) O(n+nlogn)

空间复杂度
程序中变量 tmpans 等占用了一些辅助空间,这些辅助空间都是常数阶的,因此空间复杂度为 O ( 1 ) O(1) O(1)


补充

代码参考

C语言实现

C++语言、python语言实现


大佬营友们的笔记

  1. Mr Robot http://t.csdn.cn/VsSDR
  2. 破晓之翼 http://t.csdn.cn/cPJfr
  3. Lq@@ https://blog.csdn.net/flq18210105507/article/details/127507051?spm=1001.2014.3001.5501
  4. 梦幻精灵_cq http://t.csdn.cn/uLfrx
  5. 随风飘絮 http://t.csdn.cn/88Xl7
  6. 小冷coding http://t.csdn.cn/ex8QJ
  7. Kevin_Opt http://t.csdn.cn/X0Uyy
  8. -北天- http://t.csdn.cn/lumsR
  9. 梦幻精灵_cq http://t.csdn.cn/kNdvS
  10. 随风飘絮 http://t.csdn.cn/7Zty6
  11. Kevin_Opt http://t.csdn.cn/Chkgx

你可能感兴趣的:(#,趣学算法2版,贪心算法,算法)