有关期末复习的贪心题目——课程表III

题目

解题思路

这道题可谓是深有感触,最近期末考试正好正在进行中,我的复习(预习)也正在进行中,我是一个经常逃课的孩子(…)

大家在期末复习的时候怎么进行先后复习的呢?
我们肯定是先复习距离考试时间最近的科目啊。而这道题给的就是每次只能处理一个科目的复习,中间不间断,然后给了你每个科目的复习时间。这就导致如果有些科目虽然是距离DDL时间近,但如果我们复习完它之后就会导致其他的DDL远一些的无法完成复习,

具体举例子如下:

假设 duration 数组是这样的 大学物理 [2, 4] 高等数学 [5, 7] 线性代数 [3, 3] 那么,按照策略,我们会先尝试修读线性代数。 然后尝试修读大学物理,这个时候我们发现竟然修了线性代数之后就修不了大学物理了;只能放弃;转而修高等数学发现也没有足够的时间了。

那合理的做法是什么呢? 就是我们这个时候需要放弃线性代数,因为线性代数和大学物理的权重是没有区别的,既然两者只能修一门,我们应该让当前累计花费的时间更少。大学物理虽然ddl比线性代数更晚,但它修读的时间也更短,如果已经要放弃一门课了,我们会放弃修读时间更长的。

总结:

  1. 我们先复习DDL时间比较近的。
  2. 如果出现复习时间超出DDL,则需要进行优化,放弃之前选择过的需要花时间最多的科目,用当前这个进行替代,能减少当前耗时!(这个的前提条件建立在优先选择DDL近的,因为这样按照时间排序后,一旦产生超过的,只要和前面最大的进行替换,耗时肯定会变得更小,所以就不会超过DDL了)

解题代码

根据解题思路得出代码的书写思路:

  1. 优先复习DDL时间近的–>利用DDL从小到大对其进行排序。
  2. 超出DDL时的替换过程–>利用优先队列进行操作即可。

cpp解法

class Solution {
public:
    int scheduleCourse(vector<vector<int>>& courses) {
        sort(courses.begin(), courses.end(), [](const auto& a, const auto& b) { return a[1] < b [1];});

        priority_queue<int> q;
        int day = 0;
        for (const auto& c: courses) {
            if (day + c[0] <= c[1]) {
                day += c[0];
                q.push(c[0]);
                continue;
            }
            if (!q.empty() && q.top() > c[0]) {
                day -= q.top();
                day += c[0];
                q.pop();
                q.push(c[0]);
            } 
            
        }

        return q.size();
    }
};

go语言有点麻烦,还需要实现一些接口才能使用Heap

go语言

func scheduleCourse(courses [][]int) int {
    sort.Slice(courses, func(i, j int) bool {
        return courses[i][1] < courses[j][1]
    })

    h := &IntHeap{}
    total := 0 // 优先队列中所有课程的总时间
    for _, course := range courses {
        if t := course[0]; total+t <= course[1] {
            total += t
            heap.Push(h, t)
        } else if h.Len() > 0 && t < (*h)[0] {
            total += t - (*h)[0]
            heap.Pop(h)
            heap.Push(h,t)
        }
    }
    return h.Len()
}

type IntHeap []int  // 定义一个类型

func (h IntHeap) Len() int { return len(h) }  // 绑定len方法,返回长度
func (h IntHeap) Less(i, j int) bool {  // 绑定less方法
	return h[i] > h[j]  // 如果h[i]<h[j]生成的就是小根堆,如果h[i]>h[j]生成的就是大根堆
}
func (h IntHeap) Swap(i, j int) {  // 绑定swap方法,交换两个元素位置
	h[i], h[j] = h[j], h[i]
}

func (h *IntHeap) Pop() interface{} {  // 绑定pop方法,从最后拿出一个元素并返回
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

func (h *IntHeap) Push(x interface{}) {  // 绑定push方法,插入新元素
	*h = append(*h, x.(int))
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值