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

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

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

ブログ    
ブログ    
ブログ    

推薦する

ITとビジネスの調和を実現する: デジタル変革にローコードが不可欠な理由

[51CTO.com クイック翻訳]ビジネスの世界では、デジタルトランスフォーメーションという言葉を...

人工知能は間違いに気づくのでしょうか?

1956年8月、10人の科学者がアメリカのダートマス大学に集まり、機械を使って知覚、推論、意思決定...

...

再び攻撃! AI+教育に注力する学百軍は、年間10億元という小さな目標を設定

「今年末までに、学覇君は年間売上高10億元を確保するという小さな目標を達成する予定です」と張凱蕾氏は...

この記事を読んで人工知能を始めましょう!

今、テクノロジーの世界で最もホットなものは何ですか?答えはおそらく人工知能、機械学習、ディープラーニ...

チューリング賞受賞者:人工知能を実装したものは、もはや人工知能とは呼ばれない

1956年、マッカーシーはダートマス大学で開催された会議で初めて「人工知能」の概念を提唱した。後に、...

人工知能の成長がデータセンターの再設計を促している

現在進行中のデータ センターの再設計の主な側面は、AI の大規模で複雑なワークロードと、グラフィック...

...

.NET8 究極のパフォーマンス最適化 プリミティブ - DateTime

序文前回の記事では列挙型の最適化について説明しました。今回は時刻形式である DateTime の最適...

ロボット工学アプリケーションは、Metaverse テクノロジーを通じてどのように普及するのでしょうか?

[[436311]]最近、Meta CEO マーク・ザッカーバーグ氏によるメタバースの推進が大きな...

警告!長距離LiDAR認識

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...

AI のゴッドファーザーであるヒントンは、なぜ自らが作り出した人工知能を恐れているのでしょうか?

ジェフリー・ヒントンは、コンピューターに学習方法を教えることに生涯を費やしてきました。今、彼は人工脳...

Dry goods: アルゴリズムの学習に役立つオープンソース プロジェクト

[[321744]]今日、LeetCode の問題やさまざまなアルゴリズム ルーチンを分析できる優れ...

世界を理解する、最新のレビューは自動運転の新しい時代を開く

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...

人工知能は過去70年間で急速に成長し始めたばかりである

[[337550]] 2019年末現在、わが国の中核人工知能産業の規模は510億人民元を超え、人工知...