代码随想录刷题记录——链表

 链表相关题目

2023-09-01

707.设计链表-leetcode 题目链接

题目:

关键点:

  • 定义成员变量:
    private:
        int _size;
        Node *_dummyHead;
  • 定义链表节点结构体和构造函数:
    复制代码
    //定义链表节点结构体
        struct Node {
            int val;
            Node *next;
            Node(int val):val(val),next(nullptr) {}
        };
    
        MyLinkedList() {
            //初始化链表
            _dummyHead = new Node(-1);//虚拟头节点
            _size = 0;//初始化链表长度为0,即[]
        }
    复制代码
  • C++ AC code:
    复制代码
    class MyLinkedList {
    public:
        //定义链表节点结构体
        struct Node {
            int val;
            Node *next;
            Node(int val):val(val),next(nullptr) {}
        };
    
        MyLinkedList() {
            //初始化链表
            _dummyHead = new Node(-1);//虚拟头节点
            _size = 0;//初始化链表长度为0,即[]
        }
        
        int get(int index) {
            if(index<0||index>_size-1) return -1;
            Node *cur = _dummyHead->next;
            while(index){
                cur = cur->next;
                index--;
            }
            return cur->val;
        }
        
        void addAtHead(int val) {
            Node *temp = _dummyHead->next;
            Node *p = new Node(val);
            _dummyHead->next = p;
            p->next = temp;
            _size++;
        }
        
        void addAtTail(int val) {
            Node *p = new Node(val);
            Node *cur = _dummyHead;
            while(cur->next!=nullptr){
                cur = cur->next;
            }
            cur->next = p;
            _size++;
        }
        
        void addAtIndex(int index, int val) {
            if(index>_size) return;
            Node *p = new Node(val);
            Node *cur = _dummyHead;
            while(index){
                cur = cur->next;
                index--;
            }
            p->next = cur->next;
            cur->next = p;
            _size++;
        }
        
        void deleteAtIndex(int index) {
            if(index>_size-1||index<0) return;
            Node *cur = _dummyHead;
            while(index){
                cur = cur->next;
                index--;
            }
            Node *temp = cur->next;
            cur->next = temp->next;
            delete temp;
            /*
            delete命令指示释放了tmp指针原本所指的那部分内存,
            被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,
            如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针
            如果之后的程序不小心使用了tmp,会指向难以预想的内存空间
            */
            tmp=nullptr;
            _size--;
        }
    private:
        int _size;
        Node *_dummyHead;
    };
    View Code
    复制代码

206. 反转链表-leetcode 题目链接

题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

关键点:

  • 双指针,pre,cur。初始条件:pre=null,cur=head;
  • C++ AC code:
    复制代码
    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            ListNode *pre = nullptr, *cur = head, *temp;
            while(cur){
                temp = cur->next;
                cur->next = pre;
                pre = cur;
                cur = temp;
            }
            return pre;
        }
    };
    View Code
    复制代码

 

2023-09-03

24. 两两交换链表中的节点-leetcode 题目链接

题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

知识点:

  模拟,注意指针操作的先后顺序

  虚拟头节点

C++ AC code:

复制代码
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *dummyHead = new ListNode(-1);
        dummyHead->next = head;
        ListNode *cur = dummyHead;
        while(cur->next){
            if(cur->next->next){
                ListNode *temp = cur->next;//dummyhead->1->2->3中指向1的指针
                cur->next = cur->next->next;
                ListNode *q = cur->next->next;//dummyhead->1->2->3中指向3的指针
                cur->next->next = temp;
                temp->next = q;
                cur = cur->next->next;
            }
            else{
                cur = cur->next;
            }
        }
        return dummyHead->next;
    }
};
View Code
复制代码

 

 

 

 

19.删除链表的倒数第N个节点 题目链接

题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

进阶:你能尝试使用一趟扫描实现吗?

知识点:

  快慢指针,slow和fast,fast先走n步,当fast指向null时,slow距null长度为n,即slow指向的是倒数第n个节点

C++ AC code:

复制代码
struct ListNode{
    int val;
    ListNode *next;
    ListNode(int x): val(x), next(nullptr) {}
};

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummyHead = new ListNode(-1);
        dummyHead->next = head;
        ListNode *slow = dummyHead, *fast = dummyHead;
        while(n+1){
            fast = fast->next;
            n--;
        }
        while(fast){
            fast = fast->next;
            slow = slow->next;
        }
        ListNode *temp = slow->next;
        slow->next = temp->next;
        delete temp;
        return dummyHead->next;
    }
};
View Code
复制代码

 

 

面试题 02.07. 链表相交  题目链接

题目:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

 

知识点:

  将A、B链表右对齐,重叠部分一 一比较节点指针是否相同,是则返回该节点,遍历后未找到则返回null

C++ AC code:

复制代码
#include<iostream>
using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x): val(x), next(nullptr) {}
};

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *curA = headA, *curB = headB;
        int lenA = 0, lenB = 0;
        while(curA){
            lenA++;
            curA = curA->next;
        }
        while(curB){
            lenB++;
            curB = curB->next;
        }
        //指针复位
        curA = headA, curB = headB;
        int gap = lenA > lenB ? lenA-lenB : lenB - lenA;
        //这里默认链表A更长
        if(lenA < lenB) swap(curA, curB);
        while(gap){
            curA = curA->next;
            gap--;
        }
        while(curA){
            if(curA == curB) return curA;
            curA = curA->next;
            curB = curB->next;
        }
        return nullptr;
    }
};
View Code
复制代码

 

 

 

142.环形链表II  题目链接

题目: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

 

思路:

  • 判断链表是否有环快慢指针,快指针每次两步,当fast==slow时,证明有环。若有环,则相遇时slow指针肯定没走完第一圈,假设头结点就是环入口,则slow指针走完一圈时fast指针走完两圈,其他情况下fast指针走完两圈时slow指针还在第一圈,即此前已经相遇。
  • 找到环的入口节点:
    • 相遇时,slow指针步数:x+y,fast指针步数:x+y+n(y+z)
    • 公式:2*(x+y)= x+y+n(y+z)==> x = (n-1)(y+z)+z,从公式中,可以看出,当p1从头结点走到环形入口节点时,p2也从相遇节点走到环形入口节点,即p1==p2时,p1或p2即为所求

C++ AC code:

复制代码
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *slow = head, *fast = head;
        while(fast&&fast->next){
            slow = slow->next;
            fast = fast->next->next;
            if(fast == slow){//快慢指针在环内相遇
                ListNode *p1 = head, *p2 = slow;
                while(p1!=p2){//x = (n-1)(y+z)+z,p1走x步后,将和p2在环入口相遇
                    p1 = p1->next;
                    p2 = p2->next;
                }
                return p1;//环入口节点
            }
        }
        return nullptr;//无环
    }
};
View Code
复制代码

 

 

总结

  • 链表主要种类:单链表,双链表,循环链表
  • 链表存储方式:节点内存中分散存储,通过指针连在一起
  • 链表增删改查
  • 链表和数组对比:

  • 必掌握知识点:链表结构体定义、双指针(链表反转)、虚拟头节点、快慢指针(判断有无环、删除倒数第n个节点)

 

posted @   DaxiaWan  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
点击右上角即可分享
微信分享提示