【链表篇】Leetcode算法题刷题心得

本文详细介绍了链表的基础知识,包括单链表的结构和操作。重点讲解了四种常见的链表操作:如何移除链表元素,如何翻转链表,判断两个链表是否相交,以及检测环形链表。文中通过实例展示了C++和Python的实现,并提供了相应的解题思路和代码示例。
摘要由CSDN通过智能技术生成

本文为个人学习总结,无任何商业用途,若涉及侵权,联系删除。


链表基础知识

  • 数组是在内存中是连续分布的,但是链表在内存中不是连续分布的。
  • 单链表的构造函数:
// 单链表
struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};
class ListNode:
    def __init__(self, val, next=None):
        self.val = val
        self.next = next
  • 链表的增添和删除都是O(1)操作,也不会影响到其他节点。

一、移除链表元素

注意事项:

  • c/c++ 移除链表节点记得释放移除节点的内存
  • 设置一个虚拟节点便于遍历移除操作

例题: 删除链表的倒数第N个节点移除链表元素

二、翻转链表

例题:反转链表

// 双指针法
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};
//递归法
class Solution {
public:
    ListNode* reverse(ListNode* pre,ListNode* cur){
        if(cur == NULL) return pre;
        ListNode* temp = cur->next;
        cur->next = pre;
        // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
        // pre = cur;
        // cur = temp;
        return reverse(cur,temp);
    }
    ListNode* reverseList(ListNode* head) {
        // 和双指针法初始化是一样的逻辑
        // ListNode* cur = head;
        // ListNode* pre = NULL;
        return reverse(NULL, head);
    }

};

三、链表相交

思路:双指针指向两链表头,分别遍历两次链表,节点相同时为相交节点
例题: 两个链表是否相交

ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    // p1 指向 A 链表头结点,p2 指向 B 链表头结点
    ListNode p1 = headA, p2 = headB;
    while (p1 != p2) {  // 遍历A与B结束后还没有找到相同节点,两指针都指向空节点,退出循环。
        // p1 走一步,如果走到 A 链表末尾,转到 B 链表
        if (p1 == null) p1 = headB;
        else            p1 = p1.next;
        // p2 走一步,如果走到 B 链表末尾,转到 A 链表
        if (p2 == null) p2 = headA;
        else            p2 = p2.next;
    }
    return p1;
}

四、环形链

思路:快慢指针,快指针速度时慢指针的两倍,若相交,则有环;相交后,一个指针回到原点,再相同速度直到相交为环入口。
例题:环形链表I环形链表II

ListNode detectCycle(ListNode head) {
    ListNode fast, slow;
    fast = slow = head;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow) break;
    }
    // 上面的代码类似 hasCycle 函数
    if (fast == null || fast.next == null) {
        // fast 遇到空指针说明没有环
        return null;
    }

    // 重新指向头结点
    slow = head;
    // 快慢指针同步前进,相交点就是环起点
    while (slow != fast) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值