[leetcode] Swap Nodes in Pairs

来源:互联网 发布:手机淘宝怎么代购 编辑:程序博客网 时间:2024/06/05 15:55

原题链接:https://leetcode.com/problems/swap-nodes-in-pairs/

我在github上的leetcode仓库:https://github.com/cooljacket/leetcodes

题意

把单链表相邻的两个元素,两两交换,只能操作节点,而不能单单交换节点的值。比如1->2->3->4,将变成2->1->4->3(即1和2交换,3和4交换)。

思路

  1. 对于长度小于2的链表,特判一下,保证下面的算法处理的都是长度至少为2的链表,就不需要对边界做太多的考虑了!
  2. 长度为偶数这个容易,刚好两两交换;但是奇数个结点呢?那当然是最后一个结点没有人跟它交换,所以就不变了,比如1->2->3变成2->1->3。
  3. 我把相邻两个结点交换位置,抽象成:把前者从链表中删掉,然后插入到后者的后面去。比如before->A->B->after,先把A拿掉,变成before->B->after,然后把A插入到B的后面,变成:before->B->A->after,是不是容易理解得多?
  4. 注意根据3中的描述,before应该是一个不为NULL的结点,但是对于头部的两个结点的交换来说,它们并没有before结点,所以也需要特殊处理一下,简单做,就是把前者插入到后者后面就可以了!
  5. 为什么3中要这么抽象呢?因为我觉得写一堆的赋值next的语句只会把人给绕晕,但是明明链表这种问题就是跟小时候堆积木是一样简单的,所以我想抽象成很容易理解的操作来实现。

代码

/*问题要求:1)将单链表相邻两个节点交换;2)只能使用常数空间;3)只能改变节点,不能只改变节点的值。*/class Solution {public:    ListNode* swapPairs(ListNode* head) {        // 首先排除空链表和只有一个元素的链表的情况        if (head == NULL || head->next == NULL)            return head;        // 头部的两个元素做特殊处理,交换相当于把头部插入到第二个节点后面而已        // 所以before元素的值是head,而新的头部的值是原来的第二个节点        ListNode *before = head, *newHead = head->next, *tmp;        insertAfter(newHead, head);        // 保证始终都有两个元素可以做交换,因为如果只剩下一个元素,就可以直接终止了        // 在before->A->B->after模型里,交换前,before->next就是指A,before->next->next就是指B        while (before->next != NULL && before->next->next != NULL) {            // 这个交换动作其实可以等价抽象为:将第一个节点拿掉,插入到第二个节点后面!            tmp = deleteAfter(before);            insertAfter(before->next, tmp);            before = tmp;        }        return newHead;    }    void insertAfter(ListNode *node, ListNode *toInsert) {        toInsert->next = node->next;        node->next = toInsert;    }    ListNode* deleteAfter(ListNode *node) {        ListNode *toDelete = node->next;        if (toDelete != NULL)            node->next = toDelete->next;        return toDelete;    }};
1 0