将给定问题优化为线性时间,而无需担心空间

时间:2019-05-16 00:36:09

标签: algorithm optimization data-structures time-complexity

给出人员日程表的会议开始时间和结束时间的列表,找到给定时间的人数。时间将以整数形式给出。例如:

输入为

[ [ 12, 14] ,[12,15],[14,16],[13,15]] 

输出应返回

[ 0,0,0,0,0,0,0,0,0,0,0,2,3,4,3,1]

如何在线性时间内完成?

我可以在O(n*m)中做到这一点。

要查找每个输出,请扫描输入并查找给定时间内的总人数。这需要O(n*m) n =输入的大小,m =输出的大小

2 个答案:

答案 0 :(得分:1)

在O(n + m)时间内完成此操作的技巧是:

  1. 找到所需的输出数组的大小(O(n)时间)
  2. 分配out数组并用零(O(m)时间)填充它
  3. 对于输入中的每个[a,b]out[a]+=1; out[b+1]-=1(O(n)次)
  4. 将输出中的每个元素替换为该点之前所有元素的累加和。 (O(m)时间)。例如for (int i=1; i<out.length; ++i) out[i]+=out[i-1];

答案 1 :(得分:0)

显而易见的算法效果很好:

def schedule(spans):
  s = [0] * max(map(max, spans))
  for lo, hi in spans:
    for t in range(lo - 1, hi):
      s[t] += 1
  return s

print str(schedule([[12, 14],[12,15],[14,16],[13,15]]))

这是O(L + n),其中L是所有跨度的总长度,n是输出的大小。

然后:

$ python foo.py
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 3, 1]

现在,如果您有许多重叠的间隔,则可以使用一维扫掠线算法来计算O(n log n + m)时间的结果,其中n是数字间隔,m是输出时间单位的数量。

类似这样的东西,尽管我一点也不声称这是完全正确的:

def schedule_faster(spans):
  events = []
  for lo, hi in spans:
    events.append((lo, '+'))
    events.append((hi + 1, '-'))
  events.sort()
  s = [0] * max(map(max, spans))
  n = 0
  t_last = events[0][0]
  for t, dir in events:
    if t != t_last:
      for i in range(t_last - 1, t - 1):
        s[i] = n
      t_last = t
    n += 1 if dir == '+' else -1
  return s

实际上,如果您使用基数排序或其他伪线性时间排序算法,则实际上它变为O(n + m)。