[26] 2つの順序付けられたリンクリストをマージする|並べ替えられたリンクリスト内の重複要素を削除する(LeetCode 21 | 83)

2つの順序付けられたリンクリストを組み合わせる

問題の説明

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

問題解決のアイデア

最初に頭に浮かぶのは、L1のノードを1つずつスキャンすることです。ノードごとに、前者がL2以下で後者が大きい位置を見つけ、のノードを挿入します。それにL1。このためには、ヘッドノードをL2に追加する必要があります。ヘッドノードの値は、-101、つまり、タイトル-1で指定されたノードの最小値に割り当てられます。しかし、私はコードでそれを達成することができませんでした...

以下は公式ソリューションからのものです:

反復法:

最終的な戻り結果のセンチネルノードプリヘッドを設定します。前のポインタを維持し、そのノードの隣を現在のl1とl2の小さい値で毎回ポイントし、l1またはl2がnullを指すまで繰り返します。最後に、トラバースされていないリンクリストが最後に接続されます。

class Solution {
    
    
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    
    
        ListNode* preHead = new ListNode(-1);

        ListNode* prev = preHead;
        while (l1 != nullptr && l2 != nullptr) {
    
    
            if (l1->val < l2->val) {
    
    
                prev->next = l1;
                l1 = l1->next;
            } else {
    
    
                prev->next = l2;
                l2 = l2->next;
            }
            prev = prev->next;
        }
        // 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
        prev->next = l1 == nullptr ? l2 : l1;

        return preHead->next;
    }
};

再帰:

最初に共有する興味深いことは、パブリックアカウントで見られる大物が共有する再帰的なデバ​​ッグ方法ですが、この質問では使用されていませんが、再帰的なデバ​​ッグのヒントについての私の考えには影響しません

この質問の再帰的な考え:

l1またはl2が空の場合、マージする必要はなく、空でないリンクリストが直接返されます。それ以外の場合、l1の現在の値がl2より小さい場合は、l1の次のリンクリストとl2のリンクリストの隣にl1をポイントします(つまり、小さい値の後に大きい値を置きます)。それ以外の場合は、l2の次のリンクリストの隣にl2をポイントします。 l1とマージした後。

class Solution {
    
    
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    
    
        if (l1 == nullptr) {
    
    
            return l2;
        } else if (l2 == nullptr) {
    
    
            return l1;
        } else if (l1->val < l2->val) {
    
    
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        } else {
    
    
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    }
};

ソートされたリスト内の重複する要素を削除します

問題の説明

ソートされたリンクリストを指定して、重複するすべての要素を削除し、各要素が1回だけ表示されるようにします。

問題解決のアイデア

アイデアは、curポインターを使用して現在のノードをポイントし、tempを使用して現在のノードの値を格納し、それを次のノードの値と比較します。等しい場合は、次のノードを削除します。等しくない場合、curポインタは1つ進みます。

class Solution {
    
    
public:
    ListNode* deleteDuplicates(ListNode* head) {
    
    
        if(!head)   return head; //链表为空
        ListNode* cur = head;
        int temp;//存储当前结点的值
        while(cur->next){
    
    
            temp = cur->val;
            if(cur->next->val == temp){
    
    //若下一个结点的值与当前结点值相等则删除下一结点
                ListNode* p = cur->next;
                cur->next = p->next;
                delete p;
            }else{
    
    //否则cur前进一个结点
                cur = cur->next;
            }
        }
        return head;
    }
};

時間計算量:O(n)はすべてのノードを1回トラバースします。
スペースの複雑さ:O(1)

経験

555 ...リンクリストがとても難しい...特に2つの順序付けられたリンクリストをマージしていて、手動でプロセスを実行したときに、リンクリストの質問が見つからなかったように感じます。最終的なコンパイル結果それはまだ間違っていました。それは忍耐力のテストです。次に、リンクリストの質問に対する再帰的な解決策を思い付くのは本当に難しいです!主な目的は、他の種類の質問を行うときに再帰を使用することです。データ構造の詳細を脇に置いて、再帰の意味を直接理解することはできますが、リンクリストに直面すると、それがどのようになっているのかわかりません。リンクリストの場合、再帰的、下向きの再帰、上向きの戻りはどのように壊れてマージされますか?

おすすめ

転載: blog.csdn.net/qq_43424037/article/details/113405911