关键词
- 贪婪算法
- 近似算法
- NP完全问题
- 集合(Set)
集合计算
Set
并集
并集意味着将集合合并
set1 | set2 = 两个集合的合并
交集
交集意味着找出两个集合中都有的元素
set1 & set2 = 两个集合相同的部分
差集
差集意味着将从一个集合中剔除出现在另一个集合中的元素
set1 - set2 = 从set1里面减掉出现在set2的元素
解决问题
贪婪算法是为了解决一些NP完全问题,因为NP完全问题,一般随着图中的点越来越多时,算法也是越来越耗时,时间大到无法接受,所以使用贪婪算法能够快速得到一个近似的最优解。(虽然可能不是最优解)
算法时间复杂度
O(n)
基本上只需要遍历一次就能找到近似解,所以时间复杂度为O(n)
练习
比如:教室安排问题,尽可能多课程安排在一个教室上。
- 9:00~10:00 英语课
- 9:30~10:30 政治课
- 10:00~11:00 数学课
- 10:30~11:30 体育课
- 11:00~12:00 语文课
// 假设课程时间已经按照时间排好序
type Course struct {
start int
end int
name string
}
func Greedy(arr []Course) (res []Course) {
results := make([]Course, 0)
for currIndex, curr := range arr {
// 假设第一个是最早结束或者最早开始的课程
if len(results) == 0 {
results = append(results, curr)
} else {
prev := results[len(results) - 1]
var next Course
if prev.end <= curr.start {
next = curr
// 如果课程已经按照start或者end排好序了,那么就不需要这个for循环了
for i := currIndex + 1; i < len(arr); i++ {
temp := arr[i]
if prev.end <= temp.start && temp.start < next.start {
next = temp
}
}
}
results = append(results, next)
}
}
return results
}
func main() {
c1 := Course{ start: 900, end: 1000, name: "英语课" }
c4 := Course{ start: 1030, end: 1130, name: "体育课" }
c3 := Course{ start: 1000, end: 1100, name: "数学课" }
c2 := Course{ start: 930, end: 1030, name: "政治课" }
c5 := Course{ start: 1100, end: 1200, name: "语文课" }
arr := []Course{c1, c2, c3, c4, c5};
results := Greedy(arr)
fmt.Println("课程安排", results)
}
// 输出结果
$ go run main.go
课程安排 [{900 1000 英语课} {0 0 } {1000 1100 数学课} {0 0 } {1100 1200 语文课}]
小结
- 会识别什么是NP完全问题
- 遇到NP完全问题,使用贪婪算法,找到一个局部最优解
- 贪婪算法实现简单,快速