lc[链表]---24.两两交换链表中的节点

一、题目描述

个人ac代码 :

class Solution 
{
public:
    ListNode* swapPairs(ListNode* head) 
    {
        if(!head||!(head->next))return head;
        ListNode *pre=head;
        ListNode* cur=head->next;
        int cnt=0;
        while(cur)
        {
            ListNode*tmp=cur->next;//走到这边,已经确保cur->next不为空了->防止断链
            ListNode*connect=pre;
            cur->next=pre;
            pre->next=tmp;
            if(cnt==0)//第一次翻转->保存好头结点
                head=cur;
            pre=tmp;
            if(pre==nullptr||pre->next==nullptr)
                break;
            else
            {
                cur=pre->next;
                connect->next=cur;//做好连接
            }
            cnt++;
        }
        return head;
    }
};

关键:connect指针去保存上一次翻转之后的尾结点,先连接好下一组的cur指针!!!

二、参考思路和写法:

1.参考思路:

①建议使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。

②接下来就是交换相邻两个元素了,此时一定要画图,不画图,操作多个指针很容易乱,而且要操作的先后顺序   初始时,cur指向虚拟头结点,然后进行如下三步:

相应实现代码:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
        dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode* cur = dummyHead;
        while(cur->next != nullptr && cur->next->next != nullptr) {
            ListNode* tmp = cur->next; // 记录临时节点
            ListNode* tmp1 = cur->next->next->next; // 记录临时节点

            cur->next = cur->next->next;    // 步骤一
            cur->next->next = tmp;          // 步骤二
            cur->next->next->next = tmp1;   // 步骤三

            cur = cur->next->next; // cur移动两位,准备下一轮交换
        }
        return dummyHead->next;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

上述代码注意细节:

        ①虚拟头结点的设定dummy head        

        ②while条件先后顺序,先判断cur->next是否为空(为空就是偶数节点,已经考虑了head=nullptr的情况),然后再去判断cur->next->next,防止空指针报错

        ③注意需要两个指针来记录临时节点,如上图,(1)在dummyhead指向2之后,就会找不到1,所以要提前保存一下1节点的位置(2)在2指向1之后,就会断链,所以要提前保存3节点的位置。

2.补充C语言的递归&迭代方法:

//递归版本
struct ListNode* swapPairs(struct ListNode* head){
    //递归结束条件:头节点不存在或头节点的下一个节点不存在。此时不需要交换,直接返回head
    if(!head || !head->next)
        return head;
    //创建一个节点指针类型保存头结点下一个节点
    struct ListNode *newHead = head->next;
    //更改头结点+2位节点后的值,并将头结点的next指针指向这个更改过的list
    head->next = swapPairs(newHead->next);
    //将新的头结点的next指针指向老的头节点
    newHead->next = head;
    return newHead;
}
//迭代版本
struct ListNode* swapPairs(struct ListNode* head){
    //使用双指针避免使用中间变量
    typedef struct ListNode ListNode;
    ListNode *fakehead = (ListNode *)malloc(sizeof(ListNode));
    fakehead->next = head;
    ListNode* right = fakehead->next;
    ListNode* left = fakehead;
    while(left && right && right->next ){
        left->next = right->next;
        right->next = left->next->next;
        left->next->next = right;
        left = right;
        right = left->next;
    }
    return fakehead->next;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值