【leetcode】24. 两两交换链表中的节点

落花浮王杯 提交于 2021-01-21 09:38:05

前言

有些同学也许会被链表指针给搞的昏头转向,在纸上画出很久都没搞清楚。下面将介绍一种较为通用的方法:“新建链表法”,可以解决指针乱指等晕头转向的操作。只要掌握 删除节点和尾插法建表 ,大部分链表题目都可以转换为重新建表问题

“新建链表法”:即使用尾插法构建“新链表”,此处不是从新malloc链表节点,而是改变原节点的指针指向。其步骤如下:

  • 根据问题需求判断头节点是否会被改变,若有则在原链表上加上哨兵节点作为「虚拟头节点」。
  • 遍历原链表节点,把符合题意的节点“拆下来”,然后追加到“新链表”上。
  • “新链表”尾节点指针处理。(这很关键,因为保证“新链表”尾节点指针必须为NULL)

解题思路

下面以本题举例上述思想:本题意思是两个节点一组,后一个节点处理后要在前一个节点前面。

判断当前链表是否构成两个节点一组:

当前没有节点:遍历结束,所有节点已处理。

只有一个“拆下来”,追加到新链表后;
两个节点:先“拆”第二个节点并追加到新链表后;再“拆”第一个节点并追加到新链表后。
最后对“新建链表”尾节点的next指针进行置空操作。
没有让人昏头转向的指针转向操作,只涉及到如何「拆节点」和「往新链表后添加拆下的节点」。


作者:boille
链接:https://leetcode-cn.com/problems/swap-nodes-in-pairs/solution/tong-yong-lian-biao-si-lu-xin-jian-lian-p4nm8/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


​ /* 定义一个哑结点

​ 定义 end 指针表示链表最后一个元素, p 为交换的第一个元素, q 为交换的第二个元素, tmp 指向 p 的 下一次调换结点

​ 算法如下:

​ 首先将q 插入到 链表尾

​ 然后将p 加入到 链表尾

​ 更新end

​ 更新tmp, 根据tmp 更新 p, q (可能不足两组)*/

复杂度分析

空间复杂度 O(1)

时间复杂度 O(N)

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
   
   
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {
   
   }
 *     ListNode(int x) : val(x), next(nullptr) {
   
   }
 *     ListNode(int x, ListNode *next) : val(x), next(next) {
   
   }
 * };
 */
class Solution {
   
   
public:
    ListNode* swapPairs(ListNode* head) {
   
   
        
       /* 定义一个哑结点
        定义 end 指针表示链表最后一个元素, p 为交换的第一个元素, q 为交换的第二个元素, tmp 指向 p 的 下一次调换结点

        算法如下:
        首先将q 插入到 链表尾
        然后将p 加入到 链表尾
        更新end
        更新tmp, 根据tmp 更新 p, q (可能不足两组)*/
        
        ListNode* dummy = new ListNode(0);
        ListNode* end = dummy;
        ListNode* tmp = head;
        if (tmp == nullptr) {
   
   
            return dummy->next;
        } else if (tmp->next == nullptr) {
   
   
            end->next = tmp;
            tmp->next = nullptr;
             return dummy->next;
        }

        ListNode* p = tmp;
        ListNode* q = tmp->next;

        while (1) {
   
   
            // 把 q p 加入到队列尾


            end->next = q;
            tmp = q->next;
            q->next = p;
            p->next = nullptr;
            //更新end
            end= end->next->next;
            end->next = nullptr;
            //更新tmp
           
            if (tmp == nullptr) {
   
   
                break;
            } else if (tmp->next == nullptr) {
   
   

                end->next = tmp;
                tmp->next = nullptr;
          

                break;
            }
            p = tmp;
            q = tmp->next;

        }
        return dummy->next;

    }

};

心得

  • 新建链表法可以学习掌握一下
  • 可以多找几个题目操作一下
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!