Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 此问题的线性时间解_Algorithm_Language Agnostic - Fatal编程技术网

Algorithm 此问题的线性时间解

Algorithm 此问题的线性时间解,algorithm,language-agnostic,Algorithm,Language Agnostic,我在一次面试中被问到这个问题 你站在0,你必须到达一个位置X。你可以跳到D(1到D)。如果X>D,很明显,你无法在初始跳跃时到达位置X 现在,从1到N,每秒钟都有随机位置出现的分片。这是作为零索引数组a[k]给出的,其中a[k]表示在第k秒出现的分片的位置。你必须找出,在哪一秒你可以到达(或穿过)目的地X 如果可以在初始值或[0]之后返回0,或返回最小秒数。如果在所有平铺之后仍然不可能,那么返回-1 限制条件: 1你说的线性是指瓷砖数量的线性,对吗 如果是这样,这个解决方案(在Java中)只迭代

我在一次面试中被问到这个问题

你站在0,你必须到达一个位置X。你可以跳到D(1到D)。如果X>D,很明显,你无法在初始跳跃时到达位置X

现在,从1到N,每秒钟都有随机位置出现的分片。这是作为零索引数组a[k]给出的,其中a[k]表示在第k秒出现的分片的位置。你必须找出,在哪一秒你可以到达(或穿过)目的地X

如果可以在初始值或[0]之后返回0,或返回最小秒数。如果在所有平铺之后仍然不可能,那么返回-1

限制条件:
1你说的线性是指瓷砖数量的线性,对吗

如果是这样,这个解决方案(在Java中)只迭代一次tile数组

在每次迭代中,它还需要迭代D和X次,但它与平铺数组的大小成线性关系

如果听起来和你要找的相似,请告诉我

注意:为了简化,我假设位置“0”处的磁贴在第二个数字“0”处可用,因此有效地将第二个“0”视为仅存在您所站立的磁贴的时间,然后其他磁贴在第1、2秒等处出现

公共类TestTiles{
公共静态int-calculateSecond(整数x、整数d、int[]tiles){
//首先使所有位置都不可到达(false)
boolean[]posReachable=新的boolean[x+1];
//每秒钟只迭代一次
for(int second=0;second对于(int pos=tile;(pos以下建议应花费时间O(N*log(min(N,X/D))。请特别注意,这是在O(N*log(N))中,因此比您提出的算法或mcdowella提出的优先级队列算法有更好的界限;在O(N*(X+D))中,因此比eugenioy提出的算法有一个更好的界;不随D的增加而增加(正如mcdowella的数组算法、eugenioy的算法和coproc的算法所做的);而且对于固定的X,它在O(N)中

我们的想法是保留一组我们仍然需要找到路径的区间。我们将把这组区间存储在一个平衡树中,其键是区间的下界,其值是上界。当我们看到一个新的磁贴时,我们将找到包含此磁贴的区间(如果有的话),并在磁贴周围拆分该区间,扔掉任何值结果间隔小于D。当我们的地图为空时,我们就完成了

下面是Haskell中的完整实现

导入数据.Ix 导入数据。映射 导入符合条件的数据。映射为M --设置:初始间隔集仅为0到x之间的单例 搜索::Int->Int->[Int]->可能是Int search d x=search_d(insertCandidate d 0 x空) 搜索:Int->Map Int Int->[Int]->可能是Int 搜索d=去哪里 --第一个基本情况:我们找到了所有我们关心的路径 go间隔124; M.null间隔=仅为0 --第二种基本情况:我们的瓷砖用完了,但仍然没有所有的路径 什么也不做 --最后一个例子:我们需要采取一个时间步。添加一个,然后递归搜索剩余的时间步 转到间隔(平铺:平铺)=(1+)转到新间隔平铺,其中 newIntervals=案例lookupLE平铺间隔 只是(低,高)|在范围内(低,高)瓷砖 ->插入Candidate d lo瓦 .insertCandidate d瓷砖hi .删除lo $interval _->间隔 --只保留非平凡的间隔 insertCandidate::Int->Int->Int->Map Int Int->Map Int Int 插入日期d lo hi m
|hi-lo我会一个接一个地处理阵列中的磁贴,跟踪最大可达位置,并保持“挂起”磁贴的优先级队列

  • 如果瓷砖大于X,请将其扔掉
  • 如果瓷砖已经在可触及的区域内,请将其扔掉
  • 如果此时无法访问该磁贴,请将其添加到挂起队列
  • 如果磁贴扩展了可访问区域,请执行此操作,并重新处理挂起队列中当前可访问的最近磁贴,或者在此重新处理过程中变得可访问
  • (如果现在可以到达X,则停止)

  • 每个磁贴最多处理两次,每次处理0(1)步,除了在小整数优先级队列中添加和删除min的成本外,还有专门的算法-请参阅。

    [Python中的此解决方案类似于mcdowella的解决方案;但它不使用优先级队列,而是使用大小为X的数组作为最多X的位置。它的复杂性是
    O(N+min(N,X)*D)
    ,因此它不是真正的线性,而是N中的线性…]

    数组
    world
    跟踪位置1,…,X-1。通过跳到最远可达的磁贴,每个磁贴都会更新当前位置

    def jumpAsFarAsPossible(currentPos, D, X, world):
      for jump in range(D,0,-1): # jump = D,D-1,...,1
        reachablePos = currentPos + jump
        if reachablePos >= X:
          return X
        if world[reachablePos]:
          return jumpAsFarAsPossible(reachablePos, D, X, world)
      return currentPos
    
    def solve(X,D,A):
      currentPos = 0
      # initially there are no tiles
      world = X * [False]
    
      for k,tilePos in enumerate(A):
        if tilePos < X:
          world[tilePos] = True
    
        # how far can we move now?
        if currentPos+D >= tilePos:
          currentPos = jumpAsFarAsPossible(currentPos, D, X, world)
    
        # have we reached X?
        if currentPos == X:
          return k # success in k-th second
    
      return -1 # X could not be reached
    
    def跳线可能(当前位置、D、X、世界):
    对于范围(D,0,-1)内的跳跃:#跳跃=D,D-1,…,1
    可达位置=当前位置+跳转
    如果可达位置>=X:
    返回X
    如果世界[可到达位置]:
    返回跳线尽可能(可到达位置、D、X、世界)
    返回电流位置
    def解算(X,D,A):
    currentPos=0
    #最初没有瓷砖
    world=X*[错误]
    对于k,枚举(A)中的tilePos:
    如果tilePos=tilePos:
    currentPos=可能的跳线(currentPos、D、X、world)
    #我们到X了吗?
    如果currentPos==X:
    第k秒返回k#成功
    返回-1#X无法访问
    
    下面是另一种尝试:

    创建一个大小为X的数组B。初始化它
    def jumpAsFarAsPossible(currentPos, D, X, world):
      for jump in range(D,0,-1): # jump = D,D-1,...,1
        reachablePos = currentPos + jump
        if reachablePos >= X:
          return X
        if world[reachablePos]:
          return jumpAsFarAsPossible(reachablePos, D, X, world)
      return currentPos
    
    def solve(X,D,A):
      currentPos = 0
      # initially there are no tiles
      world = X * [False]
    
      for k,tilePos in enumerate(A):
        if tilePos < X:
          world[tilePos] = True
    
        # how far can we move now?
        if currentPos+D >= tilePos:
          currentPos = jumpAsFarAsPossible(currentPos, D, X, world)
    
        # have we reached X?
        if currentPos == X:
          return k # success in k-th second
    
      return -1 # X could not be reached
    
    if (X/D > N+1) return -1;  // Taking care of rounding is left as an exercise
    
    Let C = array of chunks as described above
    
    For each C[k] // This is the O(X/D) part
    {
      Let C[k].problematic = true
      Let C[k].left = -1
      Let C[k].right = -1
    }
    
    Let problematicCounter = number of elements in array C
    
    Let C[k] be the chunk that contains position 0 (usually the first one, but I'll leave open the possibility of "sentinel" chunks)
    Let C[k].problematic = false
    Let C[k].left = 0
    Let C[k].right = 0
    Decrement problematicCounter
    
    // The following steps would require tweaking if there is one single chunk on the track
    // I do not consider that case as that would imply D >= 2*N, which is kind of ridiculous for this problem
    Let C[k] be the chunk containing position X (the last position on the track)
    Let C[k].problematic = false
    Let C[k].left = X
    Let C[k].right = X
    Decrease problematicCounter
    
    // Initialization done. Now for the loop.
    // Everything inside the loop is O(1), so the loop itself is O(N)
    For each A[i] in array A (the array specifying which tile to place in second i)
    {
      Let C[k] be the chunk containing position A[i]
    
      If C[k].problematic == true
      {
        Let C[k].problematic = false;
        Decrement problematicCounter
      }
    
      If C[k].first == -1 OR C[k].first > A[i]
      {
        Let C[k].first = A[i]
    
        // Checks that C[k-1] and C[k-2] don't go off array index bounds left as an exercise
        If C[k-1].problematic == true AND C[k-2].last <> -1 AND C[k].first - C[k-2].last <= D
        {
          Let C[k-1].problematic = false
          Decrement problematicCounter
        }
    
      If C[k].last == -1 OR C[k].last < A[i]
      {
        Let C[k].last = A[i]
    
        // Checks that C[k+1] and C[k+2] don't go off array index bounds left as an exercise
        If C[k+1].problematic == true AND C[k+2].first <> -1 AND C[k+2].first - C[k].last <= D
        {
          Let C[k+1].problematic = false
          Decrement problematicCounter
        }
    
        If problematicCounter == 0 Then return k // and forget everything else
    }
    
    return -1