[leetcode] Swap Nodes in Pairs

原题链接: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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值