[M模拟] lc1721. 交换链表中的节点(模拟+周赛223_2)

1. 题目来源

链接:1721. 交换链表中的节点

2. 题目解析

链表题目考试遇到了,不要死磕,怎么投机怎么来。一般将值存到数组中进行操作后对链表进行重建,或者不要进行指针的操作,只进行值的交换。最后就是实际意义下对链表指针进行操作,进行指针指向的改变,补题这样做,直接麻烦到自闭…

注意:

  • 本题头结点可能发生改变,则需要使用虚拟头结点
  • 链表指针写法十分麻烦。尤其是当 kn-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