配列内の単語間の最小距離を見つける高速な方法

私はこの配列を持っていると考えてください:

$array = array(

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

私は2つの単語の間の最小距離を見つける必要があります。 ( 'word1'と 'word2'をこれら2つの単語とする)

この場合、 word1 word2 との間の最小距離は1である。なぜなら、第2グループの単語は '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()です)

より良いバージョンがあると思いますか?

Please note the function must return 1 in this case too:

array(
 [other words]
'word2',
'dfg',
'word1'
 [other words]
);
3
同じ数の word1 word2 は常に $ array に存在するのでしょうか?また、逆の注文を数える必要がありますか?私。あなたの例ではword2がすぐ後に続き、word1が0の距離です。
追加された 著者 Ben Swinburne,

4 答え

私は単純なループで十分だと思います。 word2 が見つかった場合は、現在の最小値と last word1 を追跡し、現在の最小値を更新します。基本的には、 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)で行うことができますが、前処理が可能で、複数のクエリに答える必要がある場合は、より高速な方法があります

2
追加された
一般に単語のリストにはw1とw2の出現数はほとんどありません
追加された 著者 dynamic,
私はいくつかのテストを実行した、それはコードのこのバージョンが遅く実行されるようだ、理由は不明だ。
追加された 著者 dynamic,
私はこれが動作すると思う、私は実際のPHPコードで答えを追加しました
追加された 著者 dynamic,
これは、テストすることがあります...
追加された 著者 dynamic,
2番目の配列を例として追加しました.taht配列のコードは、word2が最初に見つかったため動作しません。 (特に lastword1とw の間の距離を見つけることはできません)
追加された 著者 dynamic,
配列内で見つかったword1とword2の順序は重要ではないので、これはうまくいくとは思わない。 IE array( 'word2'、 'dfg'、 'word1')は、とにかくminimumun distanceとして1を返す必要があります。とにかく単純な疑似コードを提供できるのであれば、私はそれをテストできます
追加された 著者 dynamic,
w1とw2だけで構成される大きなリストを試してみてください。元のソリューションはかなり遅くなります。最悪の場合は O(n * n)です
追加された 著者 parapura rajkumar,
私は私の擬似コードを更新しました
追加された 著者 parapura rajkumar,
上記のコードを簡単に変更して、 w1 w2 最小値と w2 w1 最小値を追跡することができます。この2つの最小値は、あなたがO(n)で再び探しているものです。
追加された 著者 parapura rajkumar,

次のようにintの配列を構築する

  1. 単語の並びを上から下に繰り返す
  2. 'word1'に遭遇し、遭遇した最後の単語が 'word1'でない場合、構築されている配列にその位置を追加します。
  3. 'word2'に遭遇し、遭遇した最後の単語が 'word2'でない場合、構築されている配列にその位置を追加します。
  4. 'word2'に遭遇し、最後に見つかった単語が 'word2'だった場合、配列の最後の要素を現在の位置に更新します。

配列をスキャンして、任意の2つのペアの最小の差異を見つけます

ステップ4を行う以外はもう一度このプロセスを繰り返します。 'word2'の代わりに 'word1'

あなたの答えは2つの最小値のうち小さい方です

1
追加された
(当然、3つのループを融合して配列自体を構築することを避けることで最適化することができます - 上記は思考の援助であり、その正確さへの直感を与えるためのものです)
追加された 著者 necromancer,

パラプラに基づいて私はこれを書いた、Dunnoはなぜそれがうまくいっているようだ

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);
}
0
追加された

ポジションの配列を設定するのはなぜですか?なぜそれらを値として保存して差の絶対値を決めるのではないでしょうか?

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

  $result = new Array();

  for(i=0; i
0
追加された
上記のコードで単純にarray_uniqueを使用してください...単純です。
追加された 著者 Vigrond,
@Vigrond:いいえ、単語が等しい場合でもその配列の単語距離は3です
追加された 著者 dynamic,
この配列を考えてみましょう: codepad.org/OqcIttDD あなたのfuncは1ではなく3を返します
追加された 著者 dynamic,
こんにちは、別の配列を例として追加しました。その配列のコードは動作しません
追加された 著者 dynamic,
どのように機能しないのですか?
追加された 著者 CaldwellYSR,
うーん、私は質問を間違って読んで、あなたは彼らが2回以上発生した場合に最小距離が必要であることに気付かなかった。最新のアップデートをお試しください。私は最近、Javaをやってきたので、構文にいくつかの問題があるかもしれないので、私はPHPの構文に錆びていますが、これはうまくいくはずです。
追加された 著者 CaldwellYSR,
array_unique は使用したくないでしょう。
追加された 著者 Josh,
PHP - 日本のコミュニティ [ja]
PHP - 日本のコミュニティ [ja]
4 参加者の

このグループではPHPについて話します。 パートナー:kotaeta.com