mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
2053 字
5 分钟
最短等待时间(加工顺序问题)
2026-06-15 10:10:02

1. 什么是最短等待时间问题?#

最短等待时间问题(也叫加工顺序问题调度问题)是贪心算法里的经典问题。

问题的描述是:

nn 个顾客(或 nn 个任务)等待同一台机器(或一个服务窗口)处理。每个任务的加工时间不同。机器一次只能处理一个任务,且不能中断。应该如何安排加工顺序,才能让所有任务的总等待时间最短

生活映射

想象你只有一个收银台,面前排了一队人结账。每个人买的东西不一样多,结账时间也不同。你想让所有人”等待的总时间”最少,应该让谁先结账?

直觉就是:让买得少、结账快的人先来。买得多的人排在后面,只会让后面的人等更久。


2. 关键概念:等待时间#

要把这个问题讲清楚,先得搞清楚”等待时间”到底怎么算。

设第 ii 个被处理的任务加工时间为 tit_i(下标 ii 表示ii 个被处理的顺序,不是任务的原始编号),那么:

  • 11 个任务开始就处理,等待时间为 00
  • 22 个任务要等第 11 个任务处理完,等待时间为 t1t_1
  • 33 个任务要等前两个都处理完,等待时间为 t1+t2t_1 + t_2
  • ……
  • ii 个任务的等待时间为前 i1i-1 个任务加工时间之和
wi=k=1i1tkw_i = \sum_{k=1}^{i-1} t_k

所有任务的总等待时间为:

W=i=1nwi=i=1nk=1i1tkW = \sum_{i=1}^{n} w_i = \sum_{i=1}^{n} \sum_{k=1}^{i-1} t_k

这个双重求和看起来抽象,我们以 44 个任务为例把它展开。

n=4n=4 时,每个任务的等待时间为:

w1=0w2=t1w3=t1+t2w4=t1+t2+t3\begin{aligned} w_1 &= 0 \\ w_2 &= t_1 \\ w_3 &= t_1 + t_2 \\ w_4 &= t_1 + t_2 + t_3 \end{aligned}

总等待时间就是:

W=0+t1+(t1+t2)+(t1+t2+t3)W = 0 + t_1 + (t_1 + t_2) + (t_1 + t_2 + t_3)

展开并合并同类项:

W=3t1+2t2+1t3+0t4W = 3 \cdot t_1 + 2 \cdot t_2 + 1 \cdot t_3 + 0 \cdot t_4

可以发现一个规律:

  • t1t_1 出现在它后面 3 个任务的等待时间中,所以被计算 33 次;
  • t2t_2 出现在它后面 2 个任务的等待时间中,所以被计算 22 次;
  • t3t_3 出现在它后面 1 个任务的等待时间中,所以被计算 11 次;
  • t4t_4 是最后一个任务,后面没有任务,所以被计算 00 次。

一般地,第 kk 个任务会出现在它后面 nkn - k 个任务的等待时间中,因此它的加工时间 tkt_k 被计算 (nk)(n - k) 次。

所以总等待时间可以统一写成:

W=k=1n(nk)tkW = \sum_{k=1}^{n} (n - k) \cdot t_k
这个公式是关键

W=k=1n(nk)tkW = \sum_{k=1}^{n} (n - k) \cdot t_k 说明:排得越靠前(kk 越小)的任务,它被计入总等待时间的次数 (nk)(n-k) 就越大。要让 WW 最小,就应该让 tkt_k 小的任务占据”被计入次数多”的位置(即靠前的位置),让 tkt_k 大的任务往后排。

这正是”短任务优先”的数学根源。


3. 贪心策略#

最短等待时间问题的贪心策略是:

按加工时间从小到大排序,让耗时最短的任务先处理。

也就是经典的 最短处理时间优先(Shortest Processing Time first,SPT)规则。

算法步骤:

  1. 把所有任务按加工时间从小到大排序。
  2. 按这个顺序依次处理。
  3. 累加每个任务的等待时间,得到总等待时间 WW

实现很简单。


4. 以 4 个任务为例#

假设有 44 个任务,加工时间分别是:

t=[4, 2, 8, 1]t = [4,\ 2,\ 8,\ 1]

如果按原始顺序处理(不排序):

处理顺序任务时间等待时间
第 1 个40
第 2 个24
第 3 个84+2=64 + 2 = 6
第 4 个14+2+8=144 + 2 + 8 = 14

总等待时间:

W=0+4+6+14=24W = 0 + 4 + 6 + 14 = 24

如果按贪心策略,先排序为 [1,2,4,8][1, 2, 4, 8],再处理:

处理顺序任务时间等待时间
第 1 个10
第 2 个21
第 3 个41+2=31 + 2 = 3
第 4 个81+2+4=71 + 2 + 4 = 7

总等待时间:

W=0+1+3+7=11W = 0 + 1 + 3 + 7 = 11

对比 24241111,差距很大。短任务优先让每个排队的任务都少等一会儿,总等待时间少了超过一半。

为什么差距这么大

原始顺序里那个耗时 88 的任务排在第 33 位,把第 44 位的任务”堵”了很久。贪心策略把长任务挪到最后,它不再拖累任何人;而把它前面省下来的时间,让所有早处理的短任务都受益。


5. Java 实现#

实现分两步:先排序,再累加。维护一个”已加工时间累计值 cur”作为下一个任务的等待时间。

import java.util.Arrays;
public class MinWaitingTime {
/**
* 返回所有任务的最小总等待时间。
*
* @param times 每个任务的加工时间
* @return 最小总等待时间
*/
public static int minWaitingTime(int[] times) {
if (times == null || times.length <= 1) {
// 没有任务或只有一个任务,都不需要等待
return 0;
}
// 1. 贪心:按加工时间从小到大排序,短任务优先
Arrays.sort(times);
int total = 0; // 总等待时间
int cur = 0; // 当前累计的加工时间,也就是下一个任务的等待时间
// 2. 依次处理,累加每个任务的等待时间
for (int i = 0; i < times.length; i++) {
// 当前任务要等前面所有任务处理完,等待时间就是 cur
total += cur;
// 处理当前任务后,累计时间增加它的加工时间
cur += times[i];
}
return total;
}
public static void main(String[] args) {
int[] times = {4, 2, 8, 1};
int result = minWaitingTime(times);
System.out.println("最小总等待时间:" + result); // 输出 11
}
}

运行结果:

最小总等待时间:11

代码里两个变量要分清楚:

  • cur已经处理完的任务的总加工时间。下一个任务开始前,它已经等了这么久,所以 cur 也就是下一个任务的等待时间。
  • total:把每个任务的等待时间 cur 累加起来,得到所有任务的总等待时间。
循环里的顺序别写反

一定要先 total += cur(累加当前任务的等待时间),再 cur += times[i](把当前任务的加工时间并入累计值)。如果写反了,相当于把当前任务的加工时间也算进了它自己的等待时间,结果会偏大。


6. 复杂度分析#

  • 时间复杂度O(nlogn)O(n \log n),主要来自排序。
  • 空间复杂度O(logn)O(\log n),即排序所需的栈空间。

排序是 O(nlogn)O(n \log n),遍历累加是 O(n)O(n),总时间复杂度由排序主导。如果数据范围很小(比如加工时间都是小整数),也可以像 最优装载 那样用计数排序优化到 O(n+C)O(n + C),其中 CC 是加工时间的最大值。


7. 拓展:平均等待时间与多机调度#

7.1 平均等待时间#

题目有时问的是平均等待时间,而不是总等待时间:

Wˉ=Wn\bar{W} = \frac{W}{n}

由于 nn 是固定的,最小化总等待时间 WW 和最小化平均等待时间 Wˉ\bar{W} 是完全等价的,贪心策略不变。

7.2 如果任务有优先级或到达时间呢?#

本文讨论的是最简单的情况:所有任务同时到达,且没有优先级。一旦放松这些假设,问题会迅速变难:

假设变化问题求解方法
任务有不同的到达时间单机调度 1rjwj1 \mid r_j \mid \sum w_j一般是 NP-Hard,需要精确算法或近似
任务带权重(优先级)加权最短处理时间优先(WSPT)tj/wjt_j / w_j 排序贪心
多台机器并行多机调度问题多数情况 NP-Hard,常用 LPT 等近似算法
NOTE

带权重的版本(任务有不同的重要性)通常用 WSPT 规则:按 tjwj\dfrac{t_j}{w_j} 从小到大排序,即”单位权重耗时越短的任务越优先”。本文的 SPT 就是 wj1w_j \equiv 1 的特殊情况。

7.3 如果目标是”最大完工时间”呢?#

注意区分两个目标:

  • 总等待时间最小(本文):关心所有任务等的总和,单机下 SPT 最优。
  • 最大完工时间(makespan)最小:关心最后一个任务什么时候结束。单机下任何顺序的 makespan 都是 ti\sum t_i,与顺序无关;只有多台机器并行时,这个目标才有意义,且是 NP-Hard。

8. 总结#

最短等待时间问题的核心是:

让加工时间短的任务先处理,加工时间长的任务后处理。

核心内容如下:

  • 总等待时间公式 W=k=1n(nk)tkW = \sum_{k=1}^{n} (n-k) \cdot t_k 揭示了本质:靠前位置的系数大,应该配短任务。
  • 贪心策略:按加工时间升序排序(SPT 规则)。
  • 平均等待时间和总等待时间等价,贪心策略不变。
  • 带权重时升级为 WSPT 规则;任务有到达时间或多台机器时问题变难。

口诀:

短的先做长的后,总等最少不用愁;公式一看就明白,大权配小数最优。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

最短等待时间(加工顺序问题)
https://dawn114514.site/posts/algorithm/minwaitingtime/
作者
黎明
发布于
2026-06-15 10:10:02
许可协议
MIT

部分信息可能已经过时

目录