データ構造とアルゴリズム: リンクリストの交差、交差点を見つける

データ構造とアルゴリズム: リンクリストの交差、交差点を見つける

[[441326]]

リンクリストの交差

LeetCode の問題へのリンク: https://leetcode-cn.com/problems/intersection-of-two-linked-lists-lcci

単一リンク リストの 2 つのヘッド ノード headA と headB が指定されている場合、2 つの単一リンク リストが交差する開始ノードを見つけて返します。 2 つのリンク リストに交差がない場合は null を返します。

この図は、2 つのリンク リストがノード c1 で交差し始めていることを示しています。

タイトル データにより、チェーン構造全体にループがないことが保証されます。

関数が返された後、リンク リストは元の構造を維持する必要があることに注意してください。

例1:

例2:

例3:

アイデア

簡単に言えば、2 つのリンク リストの交差ノードのポインタを見つけることです。ここで学生は、交差点は値が等しいのではなく、ポインタが等しいことに注意する必要があります。

例として、ノード要素の値が等しい場合、ノード ポインターも等しいと想定します。

次の 2 つのリンク リストを見てください。現在、curA はリンク リスト A のヘッド ノードを指し、curB はリンク リスト B のヘッド ノードを指しています。

2 つのリンク リストの長さと 2 つのリンク リストの長さの差を計算し、図に示すように、curA を curB の末尾に一致する位置に移動します。

この時点で、curA と curB が同じかどうかを比較できます。同じでない場合は、curA と curB を同時に後方に移動します。curA == curB の場合、交差が見つかります。

それ以外の場合はループが終了し、null ポインターを返します。

C++ コードは次のとおりです。

  1. クラスソリューション{
  2. 公共
  3. リストノード *getIntersectionNode(リストノード *headA、リストノード *headB) {
  4. リストノード* curA = headA;
  5. リストノード* curB = headB;
  6. 整数lenA = 0、lenB = 0;
  7. while (curA != NULL ) { // リンクリストAの長さを見つける
  8. lenA++;
  9. curA = curA->次へ;
  10. }
  11. while (curB != NULL ) { // リンクリストBの長さを見つける
  12. lenB++;
  13. curB = curB->次へ;
  14. }
  15. curA = ヘッドA;
  16. カーソルB = ヘッドB;
  17. // curA を最長リンクリストの先頭とし、lenA をその長さとする
  18. (長さB>長さA)の場合{
  19. (lenA、lenB)を交換する。
  20. スワップ(curA, curB);
  21. }
  22. // 長さの差を求める
  23. intギャップ = lenA - lenB;
  24. // curA と curB を同じ開始点にします(終了位置は揃えます)
  25. while (ギャップ--) {  
  26. curA = curA->次へ;
  27. }
  28. // curA と curB を走査し、同じであれば直接戻ります
  29. (curA != NULL ) の場合 {
  30. もしcurA == curBの場合{
  31. curAを返します
  32. }
  33. curA = curA->次へ;
  34. curB = curB->次へ;
  35. }
  36. 戻る  NULL ;
  37. }
  38. };
  • 時間の計算量:
  • 空間の複雑さ:

その他の言語

ジャワ

  1. パブリッククラスソリューション{
  2. パブリックListNode getIntersectionNode(ListNode headA、ListNode headB) {
  3. リストノード curA = headA;
  4. リストノード curB = headB;
  5. 整数lenA = 0、lenB = 0;
  6. while (curA != null ) { // リンクリストAの長さを見つける
  7. lenA++;
  8. curA = curA.next ;
  9. }
  10. while (curB != null ) { // リンクリストBの長さを見つける
  11. lenB++;
  12. curB = curB.next ;
  13. }
  14. curA = ヘッドA;
  15. カーソルB = ヘッドB;
  16. // curA を最長リンクリストの先頭とし、lenA をその長さとする
  17. (長さB>長さA)の場合{
  18. //1. lenA、lenBを入れ替えます。
  19. int tmpLen = lenA;
  20. lenA = lenB;
  21. lenB = tmpLen;
  22. //2. swap(curA, curB);
  23. リストノード tmpNode = curA;
  24. curA = curB;
  25. curB = tmpNode;
  26. }
  27. // 長さの差を求める
  28. intギャップ = lenA - lenB;
  29. // curA と curB を同じ開始点にします(終了位置は揃えます)
  30. while (ギャップ--> 0) {  
  31. curA = curA.next ;
  32. }
  33. // curA と curB を走査し、同じであれば直接戻ります
  34. (curA != null ) の場合 {
  35. もしcurA == curBの場合{
  36. curAを返します
  37. }
  38. curA = curA.next ;
  39. curB = curB.next ;
  40. }
  41. 戻る ヌル;
  42. }
  43.  
  44. }

パイソン

  1. クラスソリューション:
  2. def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
  3. 「」 「
  4. 速度の法則によれば、より速く歩く人はより遅く歩く人に必ず追いつくでしょう。
  5. この問題では、いくつかのリンク リストは短く、1 つのリンクを歩き終えた後、別のリンク リストを歩きます。これは、より速く移動するポインタとして理解できます。
  6.  
  7. 次に、リンクされたリストの 1 つが完了したら、もう一方のリンクされたリストに進みます。交差点があれば、最終的には同じになる
  8. ロケーションエンカウンター
  9. 「」 「
  10. cur_a, cur_b = headA, headB # a と b の代わりに 2 つのポインタを使用します
  11.  
  12.  
  13. cur_a != cur_b の場合:
  14. cur_a = cur_a.next if cur_a else headB # a が終了したら b に切り替える
  15. cur_b = cur_b.next if cur_b else headA # 同様に、bが終了したらaに切り替えます
  16.  
  17. cur_aを返す

行く

  1. getIntersectionNode関数(headA, headB *ListNode) *ListNode {
  2. curA := headA
  3. カーソルB := ヘッドB
  4. 長さA、長さB:=0、0
  5. // AとBの長さを求める
  6. curA != nil {の場合
  7. curA = curA.次へ 
  8. lenA++
  9. }
  10. curB != nil の場合
  11. curB = curB.次へ 
  12. 長さB++
  13. }
  14. var ステップint  
  15. var 高速、低速 *ListNode
  16. // 長さの差を要求し、長い方のリンクリストを先にします
  17. lenA > lenBの場合{
  18. ステップ = lenA - lenB
  19. 速い、遅い = headA、headB
  20. }それ以外{
  21. ステップ = lenB - lenA
  22. 速い、遅い = headB、headA
  23. }
  24. i:=0の場合; i < ステップ; i++ {
  25. 速い = 速い。次へ 
  26. }
  27. // 2つのリンクリストを走査し、同じものを見つけたら走査から抜け出す
  28. 速い!= 遅い {
  29. 速い = 速い。次へ 
  30. 遅い = 遅い。次へ 
  31. }
  32. 早く戻る
  33. }

ジャバスクリプト

  1. var getListLen =関数(head) {
  2. len = 0、cur = headとします。
  3. while(cur) {
  4. 長さ++;
  5. cur = cur.next ;
  6. }
  7. 長さを返します
  8. }
  9. var getIntersectionNode =関数(headA, headB) {
  10. curA = headA、curB = headB とします。
  11. lenA = getListLen(headA)、
  12. lenB = getListLen(headB);
  13. lenA < lenB の場合
  14. [curA, curB] = [curB, curA];
  15. [lenA, lenB] = [lenB, lenA];
  16. }
  17. i = lenA - lenB とします。
  18. i -- > 0 の 
  19. curA = curA.next  
  20. }
  21. curA && curA !== curB の場合
  22. curA = curA.next ;
  23. curB = curB.next ;
  24. }
  25. curAを返します
  26. };

<<:  信じられない! XiaoIceのデジタルツイン仮想人物は70日間ライブ放送されましたが、誰もそれが本物の人間ではないことに気づきませんでした

>>:  AIをうまく活用したいなら、この2つの問題を早急に解決しなければなりません!

ブログ    

推薦する

...

...

...

多国籍食品流通会社Sysco CIDO:当社の成長の秘訣はIT中心

トム・ペック氏がCOVID-19パンデミックの真っ只中にシスコに入社したとき、彼の主な目標は世界最大...

文勝ビデオの次の目的地であるメタはすでにビデオ制作を開始している

テキストガイドによるビデオツービデオ (V2V) 合成は、短編ビデオの作成や映画業界全体など、さまざ...

英国は「国家AI研究リソース」としてGPUを購入するために1億3000万ドルを費やす計画だと報じられている。

8月21日、英国のリシ・スナック首相は、世界的なコンピューティング能力の競争に追いつくために、1億...

北京が初の政策実験区を設置:自動運転は今年中に試験運用へ

車に乗り込み、コードをスキャンすると、運転手が操作しなくても黒い「タクシー」が動き出す。横断歩道では...

現代の分散ストレージシステムをサポートするアルゴリズム

アプリケーションによって処理されるデータの量が増え続けるにつれて、ストレージの拡張はますます困難にな...

コンピュータビジョンを学ぶための81ページのガイド

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

避けるべきよくあるコーディングミス

人は誰でも間違いを犯す。しかし、開発者が犯す間違いの多くは回避可能です。この記事で説明した一般的な間...

ドローンは「緊急産業」がインテリジェンスの時代に移行するのに大いに役立つ

私の国は、世界で最も深刻な災害に見舞われる国の一つです。自然災害は一般的に、種類が多く、被害地域が広...

Google に行ったが、ディープラーニングはできなかった。Facebook の Tian Yuandong が人生の課題と選択について語る

初めての15分間のスピーチの準備に2か月を要し、卒業後すぐにGoogleに入社したものの歯車の一部に...

...

いつ仕事を辞めるかを予測できる 9 つの AI 活用例

[51CTO.com 速訳] 人工知能は今や脂身の多い肉となり、誰もがそれを利用し、人工知能の真髄を...

人工直感は人工知能の次の発展方向となるだろう

AI はこれまでに開発された最も強力なテクノロジーの 1 つですが、すでに 4 回の進化を経ています...