【C言語筆問題】2つの順序付きリンクリストと逆リンクリストをマージする

イベントアドレス: CSDN 21 日間学習チャレンジ

Leetcode21 - 2 つの順序付きリンク リストを結合する

トピックの説明

2 つの昇順リストを新しい昇順リストにマージして返します。新しいリンク リストは、指定された 2 つのリンク リストのすべてのノードを結合することによって形成されます。

例 1:
**入力: **l1 = [1,2,4]、l2 = [1,3,4]出力: [1,1,2,3,4,4]

画像.png

例 2:
**入力:**l1 = [ ]、l2 = [ ]出力: [ ]

例 3:
**入力:**l1 = [ ]、l2 = [0]出力: [0]

ヒント:

  • 2 つのリンクされたリストのノード数の範囲は [0, 50] です。
  • -100 <= Node.val <= 100
  • l1 と l2 は両方とも非降順です

コアコードパターン

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    
    

}

アイデア分析とコード実装(C言語)

このアイデアは実際には非常に単純です。ここでは、センチネル ノードが新しいリンク リストのヘッド ノードとして使用され、2 つのポインタを使用して 2 つのリンク リスト内のノードを相互に比較します。小さい方が最初に挿入され、最後が新しいリンク リストに挿入されます。必ず最初にリンク リストが存在します。挿入後、まだ挿入されていないリンク リストが残りのノードを新しいリンク リストに一度に挿入します。注意点がいくつかあり、まずセンチネルノードを作成し、センチネルノードを指すガードポインタを定義しますが、このときセンチネルノードの次のポインタはすぐにNULLに初期化する必要があります。ワイルド ポインターの潜在的なリスクです。list1 リンク リストと list2 リンク リストにそれぞれ対応する 2 つのポインター cur1 と cur2 を定義します。while ループの条件は次のようになりますcur1&&cur2。なぜですか? この場合、最初に挿入されたリンク リストがある限り、ループからすぐに抜け出します。ループが終了すると、どのリンク リストが挿入されなかったかに応じて、残りのすべてのノードが新しいリンク リストに末尾挿入されます。ここで使用する補助ノード - センチネル ノードはタイトルに指定されていません。最後に解放する必要がありますが、解放する前に、まずセンチネル ノードの次のポインタの内容を取り出して、それをヘッドポインタ。

画像.png
コード

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    
    
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;
    struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
    guard->next = NULL;
    struct ListNode* tail = guard;
    
    while(cur1 && cur2)
    {
    
    
        if(cur1->val > cur2->val)
        {
    
    
            tail->next = cur2;
            tail = tail->next;
            cur2 = cur2->next;
        }
        else
        {
    
    
            tail->next = cur1;
            tail = tail->next;
            cur1 = cur1->next;
        }
    }

    if(cur1)
        tail->next = cur1;
    if(cur2)
        tail->next = cur2;

    struct ListNode* head = guard->next;
    free(guard);
    return head;
}

Leetcode206 - 逆リンクリスト

トピックの説明

単一リンク リストのヘッド ノード head を指定して、リンク リストを反転し、反転したリンク リストを返してください。

リンクリートコード206

例 1:
**入力: **head = [1,2,3,4,5]出力: [5,4,3,2,1]

画像.png

例 2:
**入力: **head = [1,2]出力: [2,1]

画像.png

例 3:
**入力: **head = []出力: []

ヒント:

  • リンクリストのノード数の範囲は[0, 5000]です。
  • -5000 <= Node.val <= 5000

コアコードパターン

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseList(struct ListNode* head)
{
    
    
    
}

アイデア分析とコード実装(C言語)

1. 新しいリンクリストの先頭挿入方法

実際、配列を使用する必要があることを除いて、この質問と基本的に同じ質問がありますが、ここでは単一リンク リストが使用されています。アイデアを参考にすることもできます。新しいリンク リストを作成することもできます。ただし、配列と比較すると、ここでは新しいノードを作成する必要はなく、ノード間のポインティング関係を変更する必要があります。新しいヘッド ポインター newHead を定義し、現在のノードを見つける cur ポインターを定義し、次のノードへの next ポインターを見つけます。cur が NULL を指さない限り、cur が指すノードを新しいリンク リストに追加します。それを置くには?newHead の内容を、ノードを指す cur の次のポインタに渡し、newHead が元々指していたものを指すようにします。次に、cur が指すノードのアドレスを newHead に渡し、newHead がノードを指すようにします。これらの操作を実行する前に、まず cur->next の値を next に入れ、実行後に next の値を cur に入れる必要があることに注意してください。実際には、元のノードを新しいリンク リストに前から後ろに 1 つずつ挿入することになります。
画像.png
コード

struct ListNode* reverseList(struct ListNode* head)
{
    
    
    struct ListNode* cur = head;
    struct ListNode* newHead = NULL;

    while(cur)
    {
    
    
        struct ListNode* next = cur->next;
        cur->next = newHead;
        newHead = cur;
        cur = next;
    }

    return newHead;
}

2. 3ポインタ反転法

リンクリストはポインタで接続されているので、ポインタの指す関係を逆にすると、前のノード、現在のノード、次のノードをそれぞれ指す3つのポインタを使う方法を考えたことはありますか。ノード (prev、cur、next) の場合、cur のポイントが NULL でない限り、反転されていないノードがまだあるとみなされ、前のノードのアドレスが次のポインタに割り当てられます。 cur が指す現在のノードの値を変更して、前のノードを指すようにし、3 つのポインターを 1 ビット後方に移動し、cur が NULL を指すまでループを続けます。反転された新しいリンク リストの先頭ノードは prev で示されているので、prev に戻るだけです。
画像.png
コード

struct ListNode* reverseList(struct ListNode* head)
{
    
    
    struct ListNode* prev = NULL;
    struct ListNode* cur = head;
    struct ListNode* next = NULL;

    while(cur)
    {
    
    
        next = cur->next;
        cur->next = prev;
        prev = cur;
        cur = next;
    }
    return prev;
}

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_61561736/article/details/126283021