leetcode之621任务调度器Golang

题目描述

给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。

然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。

你需要计算完成所有任务所需要的最短时间

示例 :

输入:tasks = ["A","A","A","B","B","B"], n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B.
     在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。 

提示:

  1. 任务的总个数为 [1, 10000]
  2. n 的取值范围为 [0, 100]

算法

我要哭啦,感觉自己是个笨B。。。。

其实很简单,CPU每一轮处理一系列任务,任务的个数就是冷却时间,并且每次处理的任务必须是当前个数最多的任务。

所以对任务进行排序,每次取出数量最多的前n+1个任务,然后将这些任务的数量减1,然后再重新排序

循环上述过程,直到整个任务队列为空

需要注意的地方就是任务队列的构建:

  • 任务队列的长度为max(n+1,任务的种类),也就是说选取的长度是冷却时间和任务的种类中的较大值

代码

type task struct {
	kind byte
	num  int
}

type sortTasks []task

func (s sortTasks) Len() int {
	return len(s)
}
func (s sortTasks) Less(i, j int) bool {
	return s[i].num >= s[j].num
}
func (s sortTasks) Swap(i, j int) {
	s[i].kind, s[i].num, s[j].kind, s[j].num = s[j].kind, s[j].num, s[i].kind, s[i].num
}
func leastInterval(tasks []byte, n int) int {
	if len(tasks) == 0 {
		return 0
	}
	time := 0
	taskNum := make(map[byte]int)
	for _, t := range tasks {
		taskNum[t]++
	}
	taskQue := make([]task, len(taskNum))
	init := 0
	for t, num := range taskNum {
		taskQue[init] = task{t, num}
		init++
	}
	if len(taskQue) < n+1 {
		tmp := make([]task, n+1-len(taskQue))
        //当n+1比任务种类更多,任务队列后面就用0补齐
		for i := 0; i < len(tmp); i++ {
			tmp[i] = task{}
		}
		taskQue = append(taskQue, tmp...)
	}
	sort.Sort(sortTasks(taskQue))
	for {
		zeroIndex := 0
        //记录最后一次归零的任务是在CPU的第几个时间处理的
		for i := 0; i < n+1; i++ {
			time++
			if taskQue[i].num > 0 {
				zeroIndex = i
				taskQue[i].num--
			}
		}
		sort.Sort(sortTasks(taskQue))
		if taskQue[0].num == 0 {
			time -= (n - zeroIndex)
			break
		}
	}
	return time
}

posted @ 2020-11-26 01:48  胖胖咩  阅读(135)  评论(0)    收藏  举报