2つのリンクリストが結合するかどうかを確認します。もしそうなら、どこ?


102

この質問は古いかもしれませんが、私は答えを考えることができませんでした。

たとえば、長さが異なる2つのリストがあり、ある時点マージされます。マージポイントがどこにあるかをどのように知ることができますか?

条件:

  1. 長さがわからない
  2. 各リストを一度だけ解析する必要があります。

2つの結合されたリンクリストの例。


マージとは、その時点からリストが1つしかないことを意味します。
rplusg 2009年

リストの変更は許可されていますか?
Artelius、2009年

1
リストを変更しないと機能しないと思います。(または、一度だけ解析するという制限を回避するために、別の場所にコピーするだけです。)
GeorgSchölly2009年

2
ポイントだったかもしれません。面接官くそー!へへ
カイル・ロセンド

1
私は興味深い提案をしています...リストの共通の尾が無限に長いと仮定します。どのようにして定数メモリを使用してノードの交差を見つけることができますか?
Akusete

回答:


36

もし

  • 「変更は許可されていません」とは、「変更することはできますが、最終的には復元する必要がある」という意味でした。
  • リストを正確に2回繰り返すことができます

次のアルゴリズムが解決策です。

まず、数字。最初のリストが長さa+cで、2番目のリストが長さであるとしますb+c。ここで、cは、それらの共通の「尾」(マージポイントの後)の長さです。次のようにそれらを示しましょう:

x = a+c
y = b+c

長さがわからないので、追加の反復なしで計算xyます。あなたはその方法を見るでしょう。

次に、各リストを繰り返し、繰り返しながら逆にします!両方のイテレータが同時にマージポイントに到達した場合は、単に比較するだけでそれがわかります。そうしないと、1つのポインターが他のポインターより先にマージポイントに到達します。

その後、他のイテレーターがマージポイントに到達すると、共通テールに進みません。代わりに、以前にマージポイントに達していたリストの最初の部分に戻ります。したがって、変更されたリストの最後(つまり、他のリストの最初の開始)に到達する前に、a+b+1イテレーションを合計します。それを呼びましょうz+1

最初にマージポイントに到達したポインタは、リストの最後に到達するまで反復を続けます。それが行った反復の数は計算されるべきであり、に等しくなりxます。

次に、このポインターは反復して戻り、リストを再び逆にします。しかし、今は元々あったリストの最初に戻ることはありません!代わりに、他のリストの先頭に移動します!それが行った反復の数は計算され、に等しくなければなりませんy

したがって、次の数値がわかります。

x = a+c
y = b+c
z = a+b

そこから

a = (+x-y+z)/2
b = (-x+y+z)/2
c = (+x+y-z)/2

これは問題を解決します。


2
質問へのコメントでは、リストの変更は許可されていません。
2009年

1
私はこの答えが好きです(とてもクリエイティブです)。私が持っている唯一の問題は、両方のリストの長さがわかっていると想定していることです。
09

リストを変更することはできません。長さもわかりません。これらは制約です...とにかく、創造的な答えに感謝します。
rplusg 2009年

2
@tster、@calvin、答えは仮定ではなく、長さが必要です。インラインで計算できます。私の答えに説明を追加します。
Pは、

2
@Forethinkerで訪問ノードをハッシュしたり、見た目でマークしたりするにはO(リスト長)メモリが必要ですが、多くのソリューション(私のものを含みますが、不完全で複雑です)ではO(1)メモリが必要です。
Pが2013

156

以下は、私が見た中で最も優れている-O(N)、カウンターなし。VisionMapでの SN候補者へのインタビュー中に入手しました。

次のように対話ポインタを作成します。毎回最後まで進み、反対のリストの先頭にジャンプします。これらの2つを作成し、2つの頭を指すようにします。彼らが会うまで、それぞれのポインターを毎回1ずつ進めます。これは、1つまたは2つのパスの後に発生します。

私はまだこの質問をインタビューで使用していますが、このソリューションが機能する理由を誰かが理解するのにどれくらい時間がかかるかを確認します。


6
それは素晴らしいです!
コングホイ

2
これは良い答えですが、条件2に違反するリストを2回通過する必要があります。
2014年

2
マージポイントが存在することが保証されている場合、このソリューションは非常に洗練されています。マージポイントが存在しない場合は無限にループするため、マージポイントを検出することはできません。
方向を交互に変更

4
それは超素晴らしいです!説明:2つのリストがあります:a-b-c-x-y-zp-q-x-y-z。最初のポインタのa,b,c,x,y,z,p,q,xパス、2番目のポインタのパスp,q,x,y,z,a,b,c,x
Nikolai Golub

14
鮮やかさ。理解できない人のために、head1-> tail1-> head2->交点およびhead2-> tail2-> head1->交点から移動したノードの数を数えます。両方が等しくなります(これを確認するには、リンクされたリストのdiffタイプを描画します)。理由は、両方のポインタが同じ距離に到達する必要があるためです。したがって、IPに到達するまでに、両方のポインタが等しくなり、マージポイントができます。
adev 2017

91

パヴェルの答えは、リストの変更を必要とするだけでなく、 2回リストを反復します。

これは、各リストを2回繰り返すだけで済むソリューションです(最初にリストの長さを計算します。長さが指定されている場合、1回だけ繰り返す必要があります)。

より長いリストの最初のエントリを無視することで(マージポイントはそこに入れることはできません)、2つのポインタがリストの最後から等しい距離になるようにするという考え方です。次に、それらが結合するまで前方に移動します。

lenA = count(listA) //iterates list A
lenB = count(listB) //iterates list B

ptrA = listA
ptrB = listB

//now we adjust either ptrA or ptrB so that they are equally far from the end
while(lenA > lenB):
    ptrA = ptrA->next
    lenA--
while(lenB > lenA):
    prtB = ptrB->next
    lenB--

while(ptrA != NULL):
    if (ptrA == ptrB):
        return ptrA //found merge point
    ptrA = ptrA->next
    ptrB = ptrB->next

これは漸近的に他の答えと同じ(線形時間)ですが、おそらく定数が小さいため、おそらく高速です。しかし、私は私のもう1つの答えはもっとクールだと思います。


4
今日、私がウォッカを飲んでいたとき、私はこの質問を私の友人に提案しました、そして彼はあなたと同じ答えをあげて、それをSOに投稿するように頼みました。しかし、あなたは最初のようです。だから私はあなたのためにあなたのために+1を作るつもりだし、もう1つ+1ができたらなあ。
Pは、

2
このように+1し、リストを変更する必要もありません。また、ほとんどのリンクリスト実装では、通常、長さを提供します
keshav84

3
Pavelsが多すぎます。私のソリューションでは、リストを変更する必要はありません。
Pavel Radzivilovsky、2015年

いい答えだ。しかし、このための時間の複雑さはどうでしょうか。0(n + m)?ここで、n =リスト1のノード、m =リスト2のノード?
Vihaan Verma 2017

両方のリストで両方のポインタを移動する代わりに、2つのパスのdiff> = smallであるかどうかを確認できます。yesの場合、小さな値で小さなリストに移動し、そうでない場合はdiff + 1の値で小さなリストで移動します。diffが0の場合、最後のノードが答えです。
Vishal Anand 2017年

30

まあ、あなたが彼らが合併することを知っているなら:

あなたが次のように始めるとしましょう:

A-->B-->C
        |
        V
1-->2-->3-->4-->5

1)次の各ポインターをNULLに設定して、最初のリストを調べます。

今あなたは持っています:

A   B   C

1-->2-->3   4   5

2)次に、2番目のリストを調べ、NULL、つまりマージポイントが表示されるまで待ちます。

それらがマージすることを確認できない場合は、ポインター値にセンチネル値を使用できますが、それはエレガントではありません。


3
しかし、あなたは再度使用しないことを決して、その過程で、リストを破棄:P
カイルロセンド

@Kyle Rozendo、まあ、私のソリューションはリストを処理後に復元できるように変更します。しかし、これは概念のより明確なデモンストレーションです
P Shved

リストの変更が許可されていないことはわかりませんでした。考えてみますが、見たすべてのノードを保存しないと何も頭に浮かびません。
2009年

10
おいおい、正解だ!質問を調整するだけです:)
P Shved

23
メモリリークを作成するための優れたアルゴリズム。
Karoly Horvath 2013

14

リストを正確に2回繰り返すことができれば、マージポイントを決定する方法を提供できます。

  • 両方のリストを繰り返し、長さAとBを計算します
  • 長さの差を計算するC = | AB |;
  • 両方のリストの反復処理を同時に開始しますが、リストに追加のCステップを追加します。
  • この2つのポインタは、マージポイントで互いに出会います

8

以下は、計算が速い(各リストを1回繰り返す)ソリューションですが、大量のメモリを使用します。

for each item in list a
  push pointer to item onto stack_a

for each item in list b
  push pointer to item onto stack_b

while (stack_a top == stack_b top) // where top is the item to be popped next
  pop stack_a
  pop stack_b

// values at the top of each stack are the items prior to the merged item

2
これは、リストを2回処理するのと同じです。
GeorgSchölly、2009年

技術的には、リストを2回処理していると思いますが、それはカイル・ローゼンドのソリューションの大幅な改善です。ここで、「リストの処理」が「リンク値の読み取りとポインタの追跡」として定義されている場合、リストを1回処理する、つまり各リンク値を1回読み取り、格納してから比較すると主張できます。
2009年

間違いなく私のものよりも速くなるでしょう。
カイル・ロセンド

7

ノードのセットを使用できます。1つのリストを反復処理し、各ノードをセットに追加します。次に、2番目のリストを反復処理し、反復ごとに、ノードがセットに存在するかどうかを確認します。もしそうなら、あなたはあなたのマージポイントを見つけました:)


(Ω(n)の追加スペースのため)これは唯一のアプローチです(リストの再構築ではなく)リストを2回以上解析しないことです。リスト内のループの検出は、最初のリストでは簡単です(ノードがセットにあるかどうかを確認してください)-2番目のリストでループ検出メソッドを使用して、確実に終了します。(面接の質問はありリスニングについてだった慎重問題のステートメントに、そしてないあなたがいない、かなり爪ヒット何かに知ることが起こるハンマーを使用するにジャンプする。)
老い

6

これは間違いなく「各リストを1回だけ解析する」条件に違反しますが、亀とうさぎのアルゴリズム(循環リストのマージポイントとサイクル長を見つけるために使用)を実装しているため、リストAから開始し、 endは、リストBの先頭へのポインタであると偽って、循環リストの外観を作成します。アルゴリズムは、リストAのマージがどこまで下にあるかを正確に通知します(Wikipediaの説明によると、変数 'mu')。

また、「lambda」値はリストBの長さを示します。必要な場合は、アルゴリズム中に(NULLリンクをリダイレクトするときに)リストAの長さを計算できます。


私が言ったことのほとんどは、ただの名前だけだ。:P
カイル・ロセンドウ

どういたしまして。この解決策は、操作ではO(n)、メモリ使用量ではO(1)です(実際には2つのポインタ変数のみが必要です)。
Artelius、2009年

ええ、私の解決策が少し変わったので、以前のコメントを削除するべきでした。へへ。
カイル・ロセンド、

しかし、そもそもそれがどのように適用されたのかわかりませんか?
Artelius、2009年

アルゴリズム自体ではなく、説明がありました。多分私はそれを異なって見ますが、ちょっと。
カイル・ロセンド

3

多分私はこれを単純化しすぎていますが、最小のリストを反復して、最後のノードLinkをマージポイントとして使用していますか?

したがって、(リストの最後にある)マージポイントとしてData->Link->Link == NULL与えるエンドポイントはどこにあるのData->Linkでしょうか。

編集:

投稿した写真から、2つのリストを最初に解析します。最小のリストを使用すると、次のノードへの参照を維持できます。ここで、2番目のリストを解析するときに、参照を比較して、Reference [i]がLinkedList [i]-> Linkの参照である場所を見つけます。これにより、マージポイントが得られます。写真で説明する時間(写真にOPを重ね合わせてください)。

リンクされたリストがあります(以下に参照を示します)。

A->B->C->D->E

2つ目のリンクリストがあります。

1->2->

マージされたリストを使用すると、参照は次のようになります。

1->2->D->E->

したがって、最初の「小さい」リストをマップします(マージされたリストは長さが4で、メインリストは5であるため、これをカウントします)。

最初のリストをループし、参照の参照を維持します。

リストには以下の参照が含まれますPointers { 1, 2, D, E }

次に、2番目のリストを調べます。

-> A - Contains reference in Pointers? No, move on
-> B - Contains reference in Pointers? No, move on
-> C - Contains reference in Pointers? No, move on
-> D - Contains reference in Pointers? Yes, merge point found, break.

もちろん、ポインタの新しいリストを維持しますが、それは仕様の範囲外ではありません。ただし、最初のリストは1回だけ解析され、2番目のリストは、マージポイントがない場合にのみ完全に解析されます。それ以外の場合は、(マージポイントで)より早く終了します。


まあ、私が最初に言いたかったこととは少し異なりますが、OPが望んでいるように見えることから、これでうまくいきます。
カイル・ロセンドウ

今はもっとはっきりしています。しかし、メモリ使用量は線形です。嫌いです。
Artelius、2009年

質問はそれ以上を求めませんでした、さもなければプロセス全体がマルチスレッド化される可能性があります。これは依然としてソリューションの単純化された「トップレベル」ビューであり、コードはいくつもの方法で実装できます。:)
カイル・ロセンド

1
えっと?マルチスレッディングは、アルゴリズムが必要とする総処理能力を低下させるのではなく、処理能力をより有効に活用する方法です。そして、コードをいくつもの方法で実装できると言うのは、単なる言い訳にすぎません。
Artelius、2009年

1
これにより、「各リストの解析は1回だけ」が限界に近づきます。あなたがしているのは、一方のリストをコピーし、そのコピーに対してもう一方のリストをチェックすることだけです。
2009年

3

FC9 x86_64でマージケースをテストし、以下に示すようにすべてのノードアドレスを出力しました。

Head A 0x7fffb2f3c4b0
0x214f010
0x214f030
0x214f050
0x214f070
0x214f090
0x214f0f0
0x214f110
0x214f130
0x214f150
0x214f170


Head B 0x7fffb2f3c4a0
0x214f0b0
0x214f0d0
0x214f0f0
0x214f110
0x214f130
0x214f150
0x214f170

ノード構造を整列したため、ノードのmalloc()を実行すると、アドレスは16バイトで整列されます。少なくとも4ビットを参照してください。最小ビットは0、つまり0x0または000bです。したがって、同じ特別なケース(ノードアドレスが揃えられている)の場合も、これらの最低4ビットを使用できます。たとえば、両方のリストを先頭から末尾に移動する場合は、訪問ノードアドレスの4ビットの1または2を設定します。つまり、フラグを設定します。

next_node = node->next;
node = (struct node*)((unsigned long)node | 0x1UL);

上記のフラグは実際のノードアドレスには影響せず、SAVEDノードポインタ値にのみ影響することに注意してください。

誰かがフラグビットを設定したことがわかったら、最初に見つかったノードがマージポイントになります。完了したら、設定したフラグビットをクリアしてノードアドレスを復元します。一方、重要なことは、きれいにするために反復するときは注意する必要があることです(たとえば、node = node-> next)。フラグビットを設定したので、このようにしてください

real_node = (struct node*)((unsigned long)node) & ~0x1UL);
real_node = real_node->next;
node = real_node;

この提案は変更されたノードアドレスを復元するため、「変更なし」と見なすことができます。


+1、これは当然、「一度だけ繰り返す」ということで頭に浮かぶものです。美しいソリューション。
jman 2013

3

簡単な解決策もありますが、補助スペースが必要になります。リストをトラバースして各アドレスをハッシュマップに格納し、他のリストをトラバースして、アドレスがハッシュマップにあるかどうかを照合するという考え方です。各リストは1回だけトラバースされます。どのリストにも変更はありません。長さはまだ不明です。使用される補助スペース:O(n)ここで、「n」は最初に通過したリストの長さです。


2

このソリューションは..あなたがスペースに文句を言うかもしれtoo..though一度だけ...リストの修正は必要ありません各リストを反復する
リスト1に基本的に反復)1と配列(店舗unsigned int型の値)内の各ノードのアドレスを格納します
2)次に、list2を反復し、各ノードのアドレスに対して--->一致するかどうかを見つける配列を検索します...そうする場合、これはマージするノードです

//pseudocode
//for the first list
p1=list1;
unsigned int addr[];//to store addresses
i=0;
while(p1!=null){
  addr[i]=&p1;
  p1=p1->next;
}
int len=sizeof(addr)/sizeof(int);//calculates length of array addr
//for the second list
p2=list2;
while(p2!=null){
  if(search(addr[],len,&p2)==1)//match found
  {
    //this is the merging node
    return (p2);
  }
  p2=p2->next;
}

int search(addr,len,p2){
  i=0;  
  while(i<len){
    if(addr[i]==p2)
      return 1;
    i++;
  }
 return 0;
} 

それが有効な解決策であることを願っています...


これは、リスト自体ではなく配列の形式ですが、リストの1つを何度も繰り返します。
syockit

1

リストを変更する必要はありません。各リストを一度だけトラバースする必要がある解決策があります。

  1. 2つのスタックを作成します。たとえば、stck1とstck2とします。
  2. 最初のリストを走査し、走査する各ノードのコピーをstck1にプッシュします。
  3. ステップ2と同じですが、今回は2番目のリストをトラバースし、ノードのコピーをstck2にプッシュします。
  4. 次に、両方のスタックからポップし、2つのノードが等しいかどうかを確認します。等しい場合は、それらへの参照を保持します。いいえの場合、等しい以前のノードは、実際には探していたマージポイントです。

1
int FindMergeNode(Node headA, Node headB) {
  Node currentA = headA;
  Node currentB = headB;

  // Do till the two nodes are the same
  while (currentA != currentB) {
    // If you reached the end of one list start at the beginning of the other
    // one currentA
    if (currentA.next == null) {
      currentA = headA;
    } else {
      currentA = currentA.next;
    }
    // currentB
    if (currentB.next == null) {
      currentB = headB;
    } else {
      currentB = currentB.next;
    }
  }
  return currentB.data;
}

元の改訂では、これは最高得票の回答を綴っただけです(Pavel Radzivilovsky、2013)
greybeard

0

これは素朴な解決策です。リスト全体を走査する必要はありません。

構造化ノードに次のような3つのフィールドがある場合

struct node {
    int data;   
    int flag;  //initially set the flag to zero  for all nodes
    struct node *next;
};

2つのリストのヘッドを指す2つのヘッド(head1とhead2)があるとします。

両方のリストを同じペースで移動し、そのノードにフラグ= 1(訪問済みフラグ)を設定します。

  if (node->next->field==1)//possibly longer list will have this opportunity
      //this will be your required node. 

0

これはどう:

  1. 各リストを1回だけトラバースできる場合は、新しいノードを作成し、最初のリストをトラバースしてすべてのノードがこの新しいノードを指すようにし、2番目のリストをトラバースして、新しいノードを指しているノードがあるかどうかを確認できます(それがマージポイントです)。2番目のトラバーサルが新しいノードにつながらない場合、元のリストにはマージポイントがありません。

  2. リストを複数回トラバースすることが許可されている場合は、各リストをトラバースして長さを確認し、長さが異なる場合は、長いリストの先頭にある「余分な」ノードを省略できます。次に、両方のリストを一度に1ステップずつトラバースし、最初のマージノードを見つけます。


1.最初のリストを変更するだけでなく、破棄します。2.何度も推奨されます。
greybeard

0

Javaでの手順:

  1. 地図を作成します。
  2. リストの両方のブランチでトラバースを開始し、ノード(たとえばノードID)に関連するいくつかのユニークなものをキーとして使用して、リストのトラバースされたすべてのノードをマップに配置し、すべての最初に値として1を配置します。
  3. 最初に重複するキーが来たら、そのキーの値をインクリメントします(値が2になり、> 1になります)。
  4. 値が1より大きいキーを取得します。これは、2つのリストがマージされているノードである必要があります。

1
マージされた部分にサイクルがある場合はどうなりますか?
Rohit

しかし、エラー処理サイクルについては、これはisyiの回答に非常によく似ています
greybeard

0

「isVisited」フィールドを導入することで効率的に解決できます。最初のリストをトラバースし、最後までのすべてのノードの「isVisited」値を「true」に設定します。次に、2番目から開始して、フラグがtrueである最初のノードとBoom(そのマージポイント)を見つけます。


0

ステップ1:両方のリストの長さを見つけるステップ2:差分を見つけて、差のある最大のリストを移動するステップ3:両方のリストが同様の位置に配置されます。手順4:リストを反復処理してマージポイントを見つける

//Psuedocode
def findmergepoint(list1, list2):
lendiff = list1.length() > list2.length() : list1.length() - list2.length() ? list2.lenght()-list1.lenght()
biggerlist = list1.length() > list2.length() : list1 ? list2  # list with biggest length
smallerlist = list1.length() < list2.length() : list2 ? list1 # list with smallest length


# move the biggest length to the diff position to level both the list at the same position
for i in range(0,lendiff-1):
    biggerlist = biggerlist.next
#Looped only once.  
while ( biggerlist is not None and smallerlist is not None ):
    if biggerlist == smallerlist :
        return biggerlist #point of intersection


return None // No intersection found

(私は各項目が行を開始するリストが好きでした。スペルチェッカーの使用を検討してください。)
greybeard '14 / 11/16

0
int FindMergeNode(Node *headA, Node *headB)
{
    Node *tempB=new Node;
    tempB=headB;
   while(headA->next!=NULL)
       {
       while(tempB->next!=NULL)
           {
           if(tempB==headA)
               return tempB->data;
           tempB=tempB->next;
       }
       headA=headA->next;
       tempB=headB;
   }
    return headA->data;
}

回答に説明を追加する必要があります。コードのみの回答が削除される場合があります。
rghome 2017年

0

マップまたは辞書を使用して、ノードのアドレスと値を保存します。住所がすでにMap / Dictionaryに存在する場合、キーの値が答えになります。これは私がしました:

int FindMergeNode(Node headA, Node headB) {

Map<Object, Integer> map = new HashMap<Object, Integer>();

while(headA != null || headB != null)
{
    if(headA != null && map.containsKey(headA.next))
    {
        return map.get(headA.next);
    }

    if(headA != null && headA.next != null)
    {
         map.put(headA.next, headA.next.data);
         headA = headA.next;
    }

    if(headB != null && map.containsKey(headB.next))
    {
        return map.get(headB.next);
    }

    if(headB != null && headB.next != null)
    {
        map.put(headB.next, headB.next.data);
        headB = headB.next;
    }
}

return 0;
}

0

AO(n)複雑性ソリューション。しかし、仮定に基づいています。

仮定は次のとおりです。両方のノードが正の整数のみを持っています。

logic:list1のすべての整数を負にします。次に、負の整数が得られるまで、list2を調べます。見つかったら=>受け取り、サインを正に戻して戻ります。

static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {

    SinglyLinkedListNode current = head1; //head1 is give to be not null.

    //mark all head1 nodes as negative
    while(true){
        current.data = -current.data;
        current = current.next;
        if(current==null) break;
    }

    current=head2; //given as not null
    while(true){
        if(current.data<0) return -current.data;
        current = current.next;
    }

}

0

2つのポインターを使用して、一方のポインターがnullの場合、もう一方のリストの先頭を指し、もう一方も同じように移動することができます。これにより、リストの長さが異なる場合、2番目のパスで出会います。 。list1の長さがnでlist2がmの場合、それらの差はd = abs(nm)です。彼らはこの距離をカバーし、合流点で会います。
コード:

int findMergeNode(SinglyLinkedListNode* head1, SinglyLinkedListNode* head2) {
    SinglyLinkedListNode* start1=head1;
    SinglyLinkedListNode* start2=head2;
    while (start1!=start2){
        start1=start1->next;
        start2=start2->next;
        if (!start1)
        start1=head2;
        if (!start2)
        start2=head1;
    }
    return start1->data;
}

0

のノードをlist1ハッシュセットに追加し、2番目のループを実行できます。ノードのlist2セットが既にセットに存在する場合は、それがマージノードになります。

static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {
    HashSet<SinglyLinkedListNode> set=new HashSet<SinglyLinkedListNode>();
    while(head1!=null)
    {
        set.add(head1);
        head1=head1.next;
    }
    while(head2!=null){
        if(set.contains(head2){
            return head2.data;
        }
    }
    return -1;
}

0

JavaScriptを使用したソリューション

var getIntersectionNode = function(headA, headB) {
    
    if(headA == null || headB == null) return null;
    
    let countA = listCount(headA);
    let countB = listCount(headB);
    
    let diff = 0;
    if(countA > countB) {

        diff = countA - countB;
        for(let i = 0; i < diff; i++) {
            headA = headA.next;
        }
    } else if(countA < countB) {
        diff = countB - countA;
        for(let i = 0; i < diff; i++) {
            headB = headB.next;
        }
    }

    return getIntersectValue(headA, headB);
};

function listCount(head) {
    let count = 0;
    while(head) {
        count++;
        head = head.next;
    }
    return count;
}

function getIntersectValue(headA, headB) {
    while(headA && headB) {
        if(headA === headB) {
            return headA;
        }
        headA = headA.next;
        headB = headB.next;
    }
    return null;
}

0

リンクされたリストの編集が許可されている場合、

  1. 次に、リスト2のすべてのノードの次のノードポインターをnullにします。
  2. リスト1の最後のノードのデータ値を検索します。これにより、 "hi hi fiロジックなし"で、両方のリストの1回のトラバースで交差するノードが得られます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.