2017-02-05 8 views
0

私が持っている課題についての質問は、新しいリストを生成するLinkedListをθ(N)回反転するアルゴリズムを書くことです。JavaでLinkedListを反転するこのアルゴリズムがθ(N)に合わないのはなぜですか?

私が思いついたコードは、時間の要件を満たしていないため、私はその理由を理解できません。

public Node reverse() { 

    if (this == Node.NIL) { 
     return Node.NIL; 
    } 

    if (this.getNext() == Node.NIL) { 
     return new Node(this.getItem(), this.getNext()); 
    } 

    Node curNode = new Node(this.getItem(), this.getNext()); 
    Node front = curNode; 

    Node nextNode = null; 
    Node prevNode = null; 

    while (curNode.getNext() != Node.NIL) { 
     nextNode = new Node(curNode.next.item, curNode.next.next); 
     curNode.next = prevNode; 
     prevNode = curNode; 
     curNode = nextNode; 
    } 

    curNode.next = prevNode; 
    front.setNext(Node.NIL); 
    return curNode; 
} 

あり、常に逆転させるために用意リストに作成された最初のノードであるNode.NILと呼ばれるべきNILと呼ばれるノードがあるので、Node.NILは次のノードである場合は、になりますリストの最後。

各ノードには、「next」と「item」の2つの属性があります。「next」はリストの次のノードで、「item」は持ち歩くデータで、この場合はObjectです。

これは(NCASES = 20)が使用されている試験である:

@Test 
public void testReverseTiming() { 
    int i; 
    long diff = 0; 
    for (i = 0; i < NCASES - 1; i++) { 
     long start = System.nanoTime(); 
     Node result = nodes2[i].reverse(); 
     long end = System.nanoTime(); 
     diff = end - start; 
     if (diff/1000000 > 250) { 
      i++; 
      break; 
     } 
    } 
    long start = System.nanoTime(); 
    Node result = nodes2[i].reverse(); 
    long end = System.nanoTime(); 
    long diff2 = end - start; 
    double ratio = (double) diff2/(double) diff; 
    assertTrue("reverse should scale linearly with list size", ratio > 1.2); 
    assertTrue("reverse should scale linearly with list size", ratio < 2.5); 
} 

それは1.2と2.5の間であることが必要であるのに対し、自分のコードは、25から35までの範囲を生成する比率。

+2

これはO(n)のようです。光り輝く非効率なことをしない限り、私は常にO(n)になることを期待しています。 – Carcigenicate

+0

@Carcigenicate質問の編集内容をご覧ください。 – waddington

+1

私はあなたがテストでやっていることを実際には得られません。そして、私は 'reverse'のwhileループがリスト内の要素と同じくらい多くの回数実行されることを期待しています(アルゴリズムが正しいと仮定して、私はあまりにもそれを見て疲れています)。 (n)。複雑さを検証するために実際にアルゴリズムのタイミングを聞いたことはありません。それが正確であるためには、あまりにも多くのことが起こっている可能性があります。 – Carcigenicate

答えて

3

あなたのコードは1回だけリストを反復しているようですから、実際はO(n)と思われます。

ただし、実際のパフォーマンスはメモリ割り当て(大規模なデータセットのOSコールを含む)とガベージコレクションに依存するため、外観内にオブジェクトを割り当てます(new Node())。どちらも不確定な時間がかかります。これは、アルゴリズム(理論上は)がO(n)であっても、測定ランタイムがn以外の要因に依存することを意味します。

新しいノードを作成する代わりに、既存のノードのリンクを変更するアルゴリズムを書き直そうとする必要があります。 (私は割り当てが既存のリストを元の位置に戻し、リストの逆コピーを作成しないと仮定します)

+0

あなたがタイミングについて言うことはかなり意味があるので、それが問題だと思います。残念ながら私は新しいリストを返さなければなりません。既存のリストを元に戻す必要はありません。 – waddington

関連する問題