线段旅行的面试难题


10

在length为的数字行上M,其中0 < M <= 1,000,000,000您给N1 < N <= 100,000)整数对点。在每对中,第一个点表示对象当前所在的位置,第二个点表示对象应移动到的位置。(记住的second一点可能是更小的first)。

现在,假设您从这一点开始,0并有一个可以容纳1物体的推车。您希望将所有对象从其初始位置移动到各自的最终位置,同时沿数字线移动最短距离(而不是位移)。你必须结束点M

现在,我一直试图将这个问题简化为一个更简单的问题。老实说,我什至都没有想到过蛮力(可能贪婪)的解决方案。但是,我的第一个想法是将后退运动退化为两个前进运动,但这似乎并非在所有情况下都有效。

3在这里绘制了这些样本测试用例:http://i.stack.imgur.com/zRv4Q.png

第一个测试用例的答案是12。首先,您red在位置拿起物品0。然后移动到点6(距离= 6),red暂时放下该项目,然后拿起该green项目。然后,您移至点5(距离= 1)并放下该green项目。然后,您移至点6(distance = 1)并拾取放置的red项目,移至点9(distance = 3),然后移至点10(distance = 1)以完成序列。

行驶的总距离为6 + 1 + 1 + 3 + 1 = 12,这是最小的可能距离。

12我相信其他两种情况的答案是。但是,我找不到解决该问题的一般规则。

任何人有任何想法吗?


如果我没记错的话,您是否不需要数据结构来计算“重叠”?否则我会以错误的方式解决它。
大卫

您仍然可以标记,如果国防部同意他将重新开放并移居
棘手怪胎

我们可以自动在站点之间移动问题(即使它们已关闭),请不要交叉发布。相反,请遵循@ratchetfreak的建议,标记为要引起注意,并提出要迁移的问题。
yannis

1
这听起来确实很刺耳,但是如果您从向右移动直到撞到一块货物开始,该怎么办。碰到货物后,放下所载物品,捡起货物,然后将其放在正确的位置。如果您碰到了另一件需要搬运的货物,请放下电流,将其捡起并处理。没有货物时,向右移动。
supersam654

1
对象是否存在于所有点或仅存在于给定点?在给定的位置上可以有多个对象吗?是否可以将对象暂时放置在最终对象之外的其他位置?
肖恩·麦克索明

Answers:


4
  1. 如果您没有人,请开始向右移动。

  2. 每当您到达一个物体而空了时,将其捡起并向其目的地移动。

  3. 每当您到达某个物体a并且已经在携带时b,请始终选择数值最小的物体(最左侧)。

  4. 如果尚未到M,请返回步骤1。

这是最佳选择:唯一可以选择的地方是在步骤3中。首先处理最左边的目的地可确保在分发两个对象时,您将尽可能地位于右侧。

为什么在developers.sx上有这个问题?是的,“面试问题”,但这只是一个很好的谜语。

PS。在实现方面,您只需要按原始位置排序的任务列表(点的整数对)即可。


1

假设您已获得这些移动,(a, b), (c, d), (e, f), ...则必须经过的最小距离abs(b - a) + abs(d - c) + abs(f - e) + ...为实际的距离abs(b - a) + abs(c - b) + abs(d - c) + abs(e - d) + ...
基本上,给定一系列移动,重点是通过交换元素来最大程度地减小“移动距离”功能。如果您将特定组合视为一个节点,并且可以从该组合中获取所有组合作为边缘,则可以使用许多启发式图搜索算法之一。光束搜索就是一个例子。


0

可能是我误解了问题,但以下情况如何:

  1. 按对的第一个数字(即当前位置)对对进行排序
  2. 沿线交换元素移动到其正确位置(您有一个temp变量)

它经过排序的事实保证了您不会来回移动元素以将它们放置在正确的位置(无论该行是表示为数组还是列表)

@templatetypedef注释后更新:
使用a HashTable存储所有对。使用每对的当前位置作为索引键。
在对上使用第二个索引。

 1. Get next pair according to index from the line.
 2. If current pair exists in hashtable then place element to its target location.  
    2.a Remove pair from hashtable.  
    2.b Make current pair the target location. Then go to step 1  
 ELSE 
        Increment current index until you get a pair present in the hashtable. Go to step 2  

您一次只能移动一个装置,所以我想必须回溯多次
大卫,

我并不是很了解您,似乎要求只是向前移动并交换编号。您已经知道当前位置和目标位置。只需交换它们(使用您说的cart变量),然后移至下对
user10326 2013年

考虑以下反例:(1,10),(10,1),(2,3),(3,4)。进行此操作的最佳方法是将对象1携带到位置10,然后在位置10拿起对象并将其携带到位置1,然后将对象2携带到3和3携带到4。起始位置的顺序是将1携带到10,然后一直返回到起点,将2携带到3,将3携带到4,然后一直到终点拿起10并带来回来了。
templatetypedef

@templatetypedef:我明白你的意思了。更新的答案
user10326 2013年

在更新后的答案中,“当前索引”是否仅指示当前位置?
大卫,

0

我倾向于基本上贪婪的算法:

建立需要移动的点的列表。由于优化这并不是必需问题的一部分,因此我无需担心如何组织它。

while !Done
    if CartIsEmpty()
        FindClosestObjectToMove()
        MoveToObject()
       LoadCart()
    else
        Destination = Cart.Contains.Target
        CurrentMove = [Location, Destination]
        SubList = List.Where(Move.Within(CurrentMove))
        if !SubList.Empty
            Destination = SubList.FindSmallest(Location, Move.Origin)
        MoveTo(Destination)
        if !Destination.Empty
            SwapCart()
            UpdateTaskList()
        else
            EmptyCart()
            DeleteTask()

我认为这涵盖了所有情况。从某种意义上说,它是递归的,但是通过更新列表而不是调用自身即可。


感谢您的回答。你能解释一下Destination = SubList.FindSmallest(Location, Move.Origin)吗?什么是Move.Origin代表?
大卫

Move.Origin是当前要移动的对象的位置-它的原点。基本上,当首先查看移动时,请执行其跨度中包含的所有较小移动。
Loren Pechtel

-1

这是不对称的旅行推销员问题。您可以将其视为图形。边将是每对(开始,结束)对,每对(0,开始)对边,以及所有其他对(完成,开始)对。

假设NP!= P,它将具有指数的预期运行时间。


3
我不确定那是真的。这是非对称TSP 的特例,因此它可能具有多项式时间解。
templatetypedef

您是否不需要像(finish,M)这样的边,M数字线的终点在哪里?
大卫

同样,指数算法太慢了,N可能会达到100,000。
大卫,

为了支持这一说法,想必您有一种方法可以将每个不对称的旅行推销员问题转化为与此描述相同的问题?
dan_waterworth

1
不一样。旅行商必须访问图的所有顶点。您的提法要求他/她四处走动。
Alexis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.