链表篇(三)

反转链表

206. 反转链表

自解

读题之后发现中心思想就是调换原指针-cur和下一个cur-next的方向,使cur->next变成cur->pre,由于这对于每一步都是相同的变化,因此想到可以用迭代的方法——从后往前翻转指针。

代码

/**
 * 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* reverseList(ListNode* head) {
        if(head == NULL) return NULL;
        if(head->next == NULL) return head;
        ListNode *last = reverseList(head->next);
        head->next->next = head;
        head->next= NULL;
        return last;
    }
};

思想解读:

对于这个单链表,为了将指针域反转,采用迭代——则不断用head->next来进行。其次,在反转过程中,利用head->next->next = head;head->next= NULL;表示节点指针域的指向变成相反了。

双指针解法

/**
 * 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* reverseList(ListNode* head) {
        ListNode *tmp ;// 保存cur的下一个节点
        ListNode *pre = NULL;
        ListNode *cur = head;
        while(cur){
            tmp = cur->next;
            cur->next = pre;//反转指针
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
};

思考

说是双指针,因为该种解题方法设计到pre和cur两个指针,通过用cur->next的语句从前往后反转指针。避免了重新定义链表指针的内存浪费行为。

两两交换链表中的节点

24. 两两交换链表中的节点

题解1——虚拟头节点

​ 为了省去每次都对头节点的特殊操作,在这里采用虚拟头节点的操作,对于这类链表转换问题,链表指针的变化是必不可少的,因此采用如下规律解题:

  • 首先需要画图,对该流程有一个认识
  • 其次操作的先后顺序需要考虑
思路图

请添加图片描述

代码
//时间复杂度:O(n)
//空间复杂度:O(1)

/**
 * 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) {
        ListNode *dummy_head = new ListNode(0);//创建虚拟头节点
        dummy_head->next = head;
        ListNode *cur = dummy_head;
        while(cur->next != NULL && cur->next->next != NULL){
            ListNode *tmp = cur->next;//1号节点
            ListNode *Node = cur->next->next->next;//3号节点
            cur->next = tmp->next;
            cur->next->next = tmp;
            cur->next->next->next = Node;
            cur = cur->next->next;
        } 
        return dummy_head->next;
    }
};
误区
  • 在进行交换指针的操作时,发现
ListNode *tmp = cur->next;//1号节点
            ListNode *Node = cur->next->next->next;//3号节点

这一步是确定原来指针所指向的节点

而在记录新的指针时,必须以虚拟头节点为原点向后衍生——等号的右侧可以是临时节点的变化。

题解2——递归

思路

对于这类都是两两交换的固定步骤,递归莫过于是一个较好的选择

//时间复杂度:O(n)
//空间复杂度: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) {
        if(head == nullptr || head->next == nullptr){
            return head;
        }
        ListNode *Newhead = head->next;
        head->next = swapPairs(Newhead->next);
        Newhead->next = head;
        return Newhead;
    }
};
思考
  • 递归的终止条件是链表中没有节点,或者链表中只有一个节点,此时无法进行交换。
  • 循环步骤:果链表中至少有两个节点,则在两两交换链表中的节点之后,原始链表的头节点变成新的链表的第二个节点,原始链表的第二个节点变成新的链表的头节点
思考
  • 递归的终止条件是链表中没有节点,或者链表中只有一个节点,此时无法进行交换。
  • 循环步骤:果链表中至少有两个节点,则在两两交换链表中的节点之后,原始链表的头节点变成新的链表的第二个节点,原始链表的第二个节点变成新的链表的头节点
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值