[Mシミュレーション] lc1721。リンクリスト内のノードを交換します(シミュレーション+毎週のコンテスト223_2)

記事のディレクトリ

1.主題の出典

リンク:1721。リンクリスト内のExchangeノード

2.トピック分析

私は試験でリンクリストの質問に遭遇しました、壊さないでください、推測する方法と来る方法。一般に、リンクリストは、操作のために値が配列に格納された後に再構築されるか、ポインタ操作が実行されず、値の交換のみが実行されます。最後は、リンクリストのポインタを実用的な意味で操作し、ポインタポイントを変更し、これを行って質問に追加することです。これは、自閉症を直接悩ませます...

注意:

  • このヘッドノードは変更される可能性があります。仮想ヘッドノードを使用する必要があります
  • リンクリストポインタの書き込みは非常に面倒です。特に、彼が多くの問題を抱えているときk、そしてn-k高速に隣接するノードは、特別なポインタ文を必要とします。コードコメントを見てください。

  • 時間計算量O(n)O(n)O n
  • スペースの複雑さO(1)O(1)O 1

コード:

// 数组+链表重建
class Solution {
    
    
public:
    ListNode* swapNodes(ListNode* head, int k) {
    
    
        vector<int> a;
        for (auto p = head; p; p = p->next) a.push_back(p->val);
        swap(a[k - 1], a[a.size() - k]);
        head = new ListNode(a[0]);
        auto tail = head;
        for (int i = 1; i < a.size(); i ++ ) 
            tail = tail->next = new ListNode(a[i]);
        return head;
    }
};

// swap()交换值
class Solution {
    
    
public:
    ListNode* swapNodes(ListNode* head, int k) {
    
    
        auto dummy = new ListNode(-1);
        dummy->next = head;
        int n = 0;
        for (auto p = dummy; p; p = p->next) n ++ ;
        auto a = dummy, b = dummy;
        for (int i = 0; i < k; i ++ ) a = a->next;
        for (int i = 0; i < n - k; i ++ ) b = b->next;
        swap(a->val, b->val);
        return dummy->next;
    }
};

// swap()交换 简易版
class Solution {
    
    
public:
    ListNode* swapNodes(ListNode* head, int k) {
    
    
        int n = 0;
        for (auto p = head; p; p = p->next) n ++ ;
        auto a = head, b = head;
        for (int i = 0; i < k - 1; i ++ ) a = a->next;
        for (int i = 0; i < n - k; i ++ ) b = b->next;
        swap(a->val, b->val);
        return head;
    }
};

// 标准链表做法,十分麻烦,边界情况十分多
class Solution {
    
    
public:
    ListNode* swapNodes(ListNode* head, int k) {
    
    
        auto dummy = new ListNode(-1);
        dummy->next = head;
        int n = 0;
        for (auto p = dummy; p; p = p->next) n ++ ;
        k ++ ;
        auto a = dummy;		// a 是第k节点的前一个
        for (int i = 0; i < k - 2; i ++ ) a = a->next;
        auto b = dummy;		// b 是倒数第k节点的前一个
        for (int i = 0; i < n - k; i ++ ) b = b->next;

        if (a == b) return dummy->next;

        auto pa = a->next, qa = pa->next;	// 该记的全部记录下来,便于指针改变
        auto pb = b->next, qb = pb->next;
        if (a->next == b) {
    
    					// 如果出现距离太近,可能交换完产生环的情况
            a->next = qa, qa->next = pa;
            pa->next = qb;
            return dummy->next;
        } else if (b->next == a) {
    
    			// 同上,这是两个特殊的边界情况
            b->next = qb, qb->next = pb;
            pb->next = qa;
            return dummy->next;
        }

        pa->next = qb, b->next = pa;		// 正常情况下,改变指针指向即可
        pb->next = qa, a->next = pb;

        return dummy->next;
    }
};

おすすめ

転載: blog.csdn.net/yl_puyu/article/details/112718344