寻找算法(内存占用少):切换灯光

时间:2013-12-22 08:20:35

标签: algorithm optimization toggle

我无法弄清楚这个问题:想象我们有M灯。起初他们都是关闭的。一个人做N动作。移动是当人将所有灯从a切换到b(包括)时。问题是:在这些动作之后将会有多少个灯泡亮起。限制是:

  • 1·; = M&LT =十亿
  • 0℃; = N< = 100000
  • 1·; = A LT; = b将= M
  • 时间限制:1秒,内存限制:16MB。

以下是输入示例:

12 3
2 6
2 6
1 3

这意味着有12个灯泡,这个人做了3次动作。在他的第一步中他切换了2到6号灯(现在我们有2,3,4,5和6)。在他的第二步中,他再次拨打了2到6的灯(所以现在所有的灯再次关闭)。在他的最后一步,他切换了1到3的光线(灯1,2和3打开​​)。所以答案是3,因为在这一系列动作之后只有3个韧带开启。

我需要一些帮助来解决我应该如何解决这个问题。简单地创建一个布尔数组并切换它是行不通的,因为数字可以达到多大。

2 个答案:

答案 0 :(得分:3)

假设您不需要动态数据结构(您有连续的更新/查询),我会使用扫描技术来解决这个问题,使用一个简单的逻辑:

1)对所有段末尾进行排序(在您的示例中,它将导致[1,2,2,3,6,6])

2)扫描列表,保持“奇偶校验”变量。每当遇到新的结束时,切换奇偶校验。扫描仅访问两端,因此扫描的任何步骤都“看到”具有相同状态的灯泡的段(打开或关闭,具体取决于奇偶校验变量)。

伪代码:

countTurnedOn(L : Array of Segment objects) {
  E = create empty list
  for (all s in L) {
    E.add(s.begin)
    E.add(s.end+1)
  }

  sort(E)

  count = 0
  parity = 0
  pos = 0
  for (i in 0 .. E.length-1) {
    newpos = E[i]
    count = count + (newpos - pos) * parity
    parity = (parity + 1) % 2
    pos = newpos
  }

  return count
} 

答案 1 :(得分:1)

问题是您希望压缩有关灯泡打开或关闭的信息。 - 没有专门用于单个灯泡的阵列中的元素(甚至是单个位),您必须专注于打开或关闭灯串。

LightString将包含以下信息:

  • 字符串的length(灯泡数量为长整数)
  • 灯泡的state on off 由1/0或布尔值表示)

你可以在动态容器中保存一系列字符串,我推荐一棵树,因为你会做很多插入(可能还有一些删除)。您从一个字符串{length:M, state:false}开始。

当您处理移动时,您有两个相同的步骤。对于第一个数字(a):

  • 您会找到包含灯泡a
  • 的字符串
  • 您将该字符串拆分为两部分(在当前部分之后插入一个新部分并调整长度)
  • 您反转(否定)以新创建的字符串开头的每个字符串的状态(分割的字符串的第二部分)。

对于b,您也可以这样做。

你的例子(第一步):

  • 开始[{length:12, state:false}]
  • 分成2 [{length:1, state:false},{length:11, state:false}]
  • 从新项[{length:1, state:false},{length:11, state:true}]
  • 开始反转状态
  • 分成6 [{length:1, state:false},{length:5, state:true},{length:6, state:true}]
  • 从新项[{length:1, state:false},{length:5, state:true},{length:6, state:false}]
  • 开始反转状态

执行某个步骤后,您可能需要进行一些清理,以保持较低的内存使用率和访问时间:合并具有相同状态的连续字符串。删除零长度字符串。