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

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

[[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つの問題を早急に解決しなければなりません!

ブログ    
ブログ    

推薦する

AIモデルのオープンソースの定義を変える必要がある

オープンソースライセンスは進化すべきだと思いますか? 2023年は人工知能(AI)の登場とともに新年...

人工知能技術が伝染病の予防と制御に役立つ

[[318426]]現在、人工知能技術は急速に発展しており、特に医療保健の分野では、生活の各分野で広...

生成的敵対ネットワークがなぜ必要なのでしょうか?

この記事は、公開アカウント「Reading the Core」(ID: AI_Discovery)か...

ニューラルネットワークの発明者、福島邦彦氏が受賞、シュミットフーバー氏とフェイフェイ・リー氏が賛辞を送る

[[429116]]最近、福島邦彦氏が2021年度バウアー賞および科学業績賞を受賞したというニュース...

...

YOLOv5の魔法:手話を学び、聴覚障害者を支援する

コンピュータービジョンはアメリカ手話を学習して聴覚障害者を助けることができるでしょうか?データサイエ...

...

Googleのジェフ・ディーンが単独著者として執筆: ディープラーニング研究の黄金の10年

コンピュータの出現以来、人類は思考できる機械を創ることを夢見てきました。 1956 年、ジョン マッ...

ビッグデータと人工知能の分野で初心者から専門家になるためのガイド

私たちは「技術の爆発」と「共有とオープンソース」の時代に生きています。先進技術の更新と反復の速度は、...

オープンモデルの重みはAIを制御不能にすると言われ、Metaはプラカードで抗議され、LeCun:オープンソースAIコミュニティは活発化している

AIの分野では、オープンソースとクローズドソースの選択については、常に意見が分かれてきました。しかし...

...

Microsoft OneDrive 3.0 が発表されました: 新しいデザイン、共有の改善、Copilot AI など

マイクロソフトは10月4日、新デザインと多くの機能改善をもたらし、Copilot AI機能を導入した...

DFSアルゴリズムは5つの島の問題を克服する

[[429450]]この記事はWeChatの公開アカウント「labuladong」から転載したもので...

中国の「データブリックス」:AIインフラの構築に真剣に取り組む

AI導入の最大の推進要因はインフラのアップグレードです。近年、ビッグデータ分析やAIなどの分野が注目...