贪心算法

176 阅读3分钟

贪心算法

是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的[算法]比如在[旅行推销员问题]中,如果旅行员每次都选择最近的城市,那这就是一种贪心算法。

例题1

假设有如下课程表, 你希望讲尽可能多的课程安排在某间教室上.

image.png

image.png

最好的做法就是:

  • 选出结束最早的课,它就是要在这间教室上的第一堂课。
  • 接下来,必须选择第一堂课结束后才开始的课。同样,你选择结束最早的课,这将是要在这间教室上的第二堂课。
  1. 选择 结束最早的课程 , 那么就是 10点结束的 美术

image.png 2. 选择 第一堂课结束后才开始的课 并且 结束最早的课程, 那么就是 数学

image.png 3. 选择 第二堂课结束后才开始的课程 并且 结束最早的课程 , 那么就是 音乐

image.png

  1. 这样课程久安排好了

image.png

贪心算法: 每一步都选择 局部的最优解, 那么 最终得到的就是全局的最优解 (感觉就像哲学里的: 量变引起质变)

例题2

本例子的集合,使用 此文章写好的集合类: 使用Typescript实现集合的操作

假设你办了个广播节目,要让全美50个州的听众都收听得到。为此,你需要决定在哪些广播台播出。在每个广播台播出都需要支付费用,因此你力图在尽可能少的广播台播出。现有广播台名单如下。

image.png

  1. 创建一个 集合(CustomSet)对象, 其中包含需要覆盖的州
let states_needs = new CustomSet(['mt', 'wa', 'or', 'id',
'nv', 'ut', 'ca', 'az'])
  1. 创建一个可供选择的广播台的对象
const stations : {
  [key: string]: any
} = {
  "kone": new CustomSet(['id', 'nv', 'ut']),
  "ktwo":  new CustomSet(['wa', 'id', 'mt']),
  "kthree":  new CustomSet(['or', 'nv', 'ca']),
  "kfour":  new CustomSet(['nv', 'ut']),
  "kfive":  new CustomSet(['ca', 'az']),
}
  1. 保存最后选择的广播台
const final_stations = new CustomSet()
  1. 遍历 所有的可供选择的广播台的对象(stations), 并且与 需要覆盖的州(states_needs),进行交集, 获取尽可能多的州,
let best_station = ''
let states_covered = new CustomSet()
for (const station of Object.keys(stations)) {
    const states_for_station: CustomSet<any> = stations[station] // 获取 广播站的 覆盖的州
    const coverd = states_needs.intersection(states_for_station) // 需要覆盖的州 与 广播站的 覆盖的州进行交集 
    const coverd_len = Array.from(coverd.keys()).length
    const states_covered_len = Array.from(states_covered.keys()).length
    if (coverd_len > states_covered_len) { // 获取 覆盖最高的 广播站
      best_station = station
      states_covered = coverd
    }
  }
  1. 将 选择出来的 广播站 添加到 final_stations, 并且 去掉 states_needs中已经从第4步选择的州
states_needs = states_needs.diff(states_covered)
final_stations.add(best_station)
  1. 如果states_needs不为空, 那么 就 从第4第开始循环,直到states_needs 为空

该部分的代码: CustomSet 的代码 在 使用Typescript实现集合的操作 提供


const stations : {
  [key: string]: any
} = {
  "kone": new CustomSet(['id', 'nv', 'ut']),
  "ktwo":  new CustomSet(['wa', 'id', 'mt']),
  "kthree":  new CustomSet(['or', 'nv', 'ca']),
  "kfour":  new CustomSet(['nv', 'ut']),
  "kfive":  new CustomSet(['ca', 'az']),
}

const final_stations = new CustomSet()

let states_needs = new CustomSet(['mt', 'wa', 'or', 'id',
'nv', 'ut', 'ca', 'az'])

while (Array.from(states_needs.keys()).length) {
  let best_station = ''
  let states_covered = new CustomSet()
  for (const station of Object.keys(stations)) {
    const states_for_station: CustomSet<any> = stations[station]
    const coverd = states_needs.intersection(states_for_station)
    const coverd_len = Array.from(coverd.keys()).length
    const states_covered_len = Array.from(states_covered.keys()).length
    if (coverd_len > states_covered_len) {
      best_station = station
      states_covered = coverd
    }
  }
  states_needs = states_needs.diff(states_covered)
  final_stations.add(best_station)
}
console.log(final_stations) // CustomSet { set: Set(4) { 'kone', 'ktwo', 'kthree', 'kfive' } }