更快地找到数组中单词之间的最小距离

时间:2011-12-19 00:36:32

标签: php arrays

考虑我有这个数组:

$array = array(

'word1',
'abc',
'abc',
'word2',
 [other words]
'word1',
'dfg'
'word2',
 [other words]
);

我需要找到2个给定单词之间的最小距离。 (让' word1'和' word2'是这两个词)

在这种情况下,word1word2之间的最小距离为1,因为在第二组单词中,它们仅由' dfg'分开。

我写了一个简单的代码,但它过于苛刻,我正在寻找更快的版本。

//> PSEUDO CODE
function minDistance( $words, $word1, $word2 ) {
    foreach( $words as $k=>$v) 
      if ( $v == $words1 )
         $positionsOfFirstWord[] = $k;

      if ( $v == $words2 )
         $positionsOfSecondWord[] = $k;


     //> If word1 or word2 was not found in the array then
     //> return max distance possibile (count($words))

     //> Now we have 2 array containg the position of both word we need.

     foreach( $positionsOfFirstWord as $v )
        foreach( $positionsOfSecondWord as $vv )
          $distance = abs($vv-$v);

}

请注意$ array中单词的顺序并不重要(这就是为什么有abs())

您认为可以有更好的版本吗?

请注意此功能必须在这种情况下返回1:

array(
 [other words]
'word2',
'dfg',
'word1'
 [other words]
);

4 个答案:

答案 0 :(得分:2)

我认为一个简单的循环就足够了。如果找到last word1,请跟踪当前最小值和word2并更新当前最小值。基本上你利用的事实是word2总是最接近找到的word1

 let minimum = INFINITY
 let lastword1 = -1
 let lastword2 =  -1
 foreach word w in words
 {

      if ( w is word1 )
      {
           lastword1 = current position;

           find distance between lastword2 and w update minimum if needed
      }

      if ( w is word2 )
      {
          lastword2 = current position;

          find distance between lastword1 and w update minimum if needed
      }

 }

您可以在O(n)中执行此操作,但如果可以完成预处理并且您需要回答多个查询,可能会有更快的方法

答案 1 :(得分:1)

构造一个int数组,如下所示

  1. 从上到下迭代单词数组
  2. 如果您遇到'word1'并且遇到的最后一个单词不是'word1',那么将该位置追加到正在构造的数组
  3. 如果您遇到'word2'并且遇到的最后一个单词不是'word2',那么将该位置追加到正在构造的数组
  4. 如果您遇到'word2'并且遇到的最后一个单词是'word2',那么将数组的最后一个元素更新为当前位置
  5. 现在扫描数组以找到任意两对之间的最小差异

    再次重复此过程,除了执行步骤4.使用'word1'而不是'word2'

    你的答案是两个最小值中的较小者

答案 2 :(得分:0)

为什么要为这些职位设置数组?为什么不将它们保存为值然后做差异的绝对值呢?

function distance($words, $first, $second) {

  $result = new Array();

  for(i=0; i<words.length; i++) {
    if($words[i] == $first) {
      $firstPos = i;
    } elseif($words[i] == $second) {
      $secondPos = i;
      $result[] = (abs($firstPos - $secondPos));
    }
  }

  // Find the smallest number in the result array
  $min = $result[0];
  for(i=0; i<result.length; i++) {
    if(result[i] < $min) {
      $min = result[i];
    }
  }

  return $min;

}

答案 3 :(得分:0)

基于parapura我写了这个,不知道为什么,但似乎它正在工作SLOWER

function minDistance2($words,$key1,$key2) {

    if ($key1 == $key2)
        return 0;

    $min = false;
    $p1 = false;
    $p2 = false;

    foreach($words as $k=>$v) {
        $calc = false;

        if ($v == $key1) {
            $p1 = $k;       
            $calc = true;
        } else if ($v == $key2) {
            $p2 = $k;
            $calc = true;
        }

        if ($calc) {
            if ($p1===false || $p2===false)
                continue;

            $d = abs($p1-$p2) - 1;

            if ($min === false || $d<$min )
                $min = $d;
        }

        if ($min!==false && $min<=0)
            return 0;
    }

    return ($min===false ? 0 : $min);
}