【中等】24-两两交换链表中的节点 Swap Nodes in Pairs

题目

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例:

给定 1->2->3->4, 你应该返回 2->1->4->3.

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/swap-nodes-in-pairs

解法

解题思路

对于一个链表,想要两两翻转,可以划分为将链表中的某个长度为2的子链翻转过来并且连接上的子问题

对于子链反转,由于长度是2,只需要让后面的节点指向前面节点即可,而对于子链连接回原链的问题,我们只需要将断开部分的前驱节点与原子链的末尾节点连接,断开部分的后驱节点与原子链的前方节点连接即可,也就是说,对于一个子问题,我们关注的是子链开始,子链结束,子链前驱,子链后驱四个节点

一个子问题解决了,我们分析一共有多少子问题,很简单,对于长度为n的链表,一共需要解决n/2个子问题,从前到后,

  1. 每一个子问题的子链开始是前一个子问题的子链后驱

  2. 每一个子问题的子链结束时子链开始位置的后第t-1位

  3. 每一个子问题的子链前驱是上一个子问题的子链结束位置

  4. 每一个子问题的子链后驱是当前子链结束的下一个节点

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void swap(ListNode* before, ListNode *start, ListNode* end, ListNode* back){
        before->next = end;
        end->next = start;
        start->next = back;
    }
    ListNode* swapPairs(ListNode* head) {
        if(head == NULL or head->next == NULL) return head;
        ListNode *res = new ListNode(0);
        res->next = head;
        ListNode* before = res, *start = head, *end = head->next;
        ListNode *back = end->next;
        while(end!=NULL){
            swap(before, start, end, back);
            if(back == NULL) return res->next;
            before = start;
            start = back;
            end = back->next;
            for(int i = 0; i < 2; ++i){
                if(back == NULL) return res->next;
                back = back->next;
            }
        }
        return res->next;
        
    }
};
posted @ 2020-04-26 18:25  陌良  阅读(155)  评论(0编辑  收藏  举报