算法训练 —— 链表(2)

news/2024/6/18 21:36:31 标签: 链表, 算法, 数据结构

目录

1. LeetCode24. 两两交换链表中的结点

2. LeetCode19. 删除链表的倒数第N个节点

3. LeetCode160.相交链表

4. LeetCode141.环形链表

5. LeetCode142.环形链表II

6. LeetCode138.复制带随机指针的链表 


1. LeetCode24. 两两交换链表中的结点

两两交换链表中的结点 

/*解法1:迭代。。设置虚拟头结点*/
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* res = new ListNode(-1);// 设置一个虚拟头结点
        res->next = head;// 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode* cur = res;
        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 res->next;
    }
};

 

 

/*解法2:递归*/
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //如果链表结点个数为0或1,这时候直接返回head,不需要交换
        if(head == nullptr || head->next == nullptr) return head;

        ListNode* prev = head;
        ListNode* cur = prev->next;
        ListNode* next = cur->next;

        //交换两个节点
        prev->next = next;
        cur->next = prev;

        //以 1->2->3->4->5->nullptr 为例
        //交换之后为 2->1->3->4->5->nullptr
        //因为head是指向1的,所有递归调用的结果返回给head->next
        head->next = swapPairs(next);
        return cur;
        
    }
};

解法2图解: 

 

//解法3:
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* newhead = head->next;
        ListNode* tmp = nullptr;
        ListNode* prev = head;
        ListNode* cur = prev->next;
        ListNode* next = cur->next;
        while(prev != nullptr && prev->next != nullptr)
        {
            cur->next = prev;
            prev->next = next;
            if(tmp != nullptr) tmp->next = cur;
            tmp = prev;
            prev = next;
            if(prev != nullptr)cur = prev->next;
            if(cur != nullptr) next = cur->next;
        }
        return newhead;
    }
};

        解法3:是不用虚拟的头结点,直接在原链表交换,是一种不错的思路,但是理解起来不是那么容易,建议上面两种方法的理解,下面是图解过程

 

 

2. LeetCode19. 删除链表的倒数第N个节点

删除链表的倒数第N个节点 

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //给链表设置一个虚拟头结点(哨兵结点),有效防止删除正数第一个的情况,避免更新头结点
        ListNode* res = new ListNode(-1);
        res->next = head;
        ListNode* fast = head;
        ListNode* slow = head;
        ListNode* prev = res;
        while(n--)//因为题目中n是有效的,所以我们让快指针先走n步
        {
            fast = fast->next;
        }
        while(fast)//然后fast和slow一起走
        {
            fast = fast->next;
            prev = slow;//一起走之前,先记录一下slow的位置,当fast走到空时,slow一定走到了倒数第n个节点上
            slow = slow->next;
        }
        prev->next = slow->next;
        return res->next;
    }
};

 

3. LeetCode160.相交链表

相交链表 

 

//解法1:
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* pA = headA;
        ListNode* pB = headB;
        //你可以算一算图中的pA走完headA从headB开始走到交点,和pB走完headB从headA开始走到交点距离是一样的
        while(pA != pB)//pA == pB时退出,表明走到了交点
        {
            // pA 将headA链表走完了,就去走headB链表
            pA = pA == nullptr ? headB : pA->next;
            // pB 将headB链表走完了,就去走headA链表
            pB = pB == nullptr ? headA: pB->next;
        }
        return pA;
    }
};

//解法2;
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* tailA = headA;
        ListNode* tailB = headB;
        int lenA = 1;
        while(tailA->next)//计算链表A的长度
        {
            ++lenA;
            tailA = tailA->next;
        }

        int lenB = 1;
        while(tailB->next)//计算链表B的长度
        {
            ++lenB;
            tailB = tailB->next;
        }
   
        if(tailA != tailB)//两个链表都走完了,但是不相等,表明一定没有交点
        {
            return nullptr;
        }
        
        int gap = abs(lenB - lenA);//算出长短链表相差多少
        ListNode* shortlist = headA;
        ListNode* longlist = headB;

        if(lenA > lenB)//这里用来准确确定长、短链表
        {
            shortlist = headB;
            longlist = headA;
        }
        
        while(gap--)//让长链表走差距步
        {
            longlist = longlist->next;
        }

        while(longlist != shortlist)//然后长链表和短链表一起走
        {
            longlist = longlist->next;
            shortlist = shortlist->next;
        }
        return longlist;
    }
};

 

4. LeetCode141.环形链表

环形链表 

思路动图:

 

双指针法:

快指针先走两步,紧接着慢指针走

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow)
            {
                return true;
            }
        }
        return false;
    }
};

5. LeetCode142.环形链表II

环形链表II 

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow)
            {
                ListNode* meet = slow;
                while(meet != head)
                {
                    meet = meet->next;
                    head = head->next;
                }
                return head;
            }
            
        }
        return nullptr;
    }
};

6. LeetCode138.复制带随机指针的链表 

 

 

class Solution {
public:
    Node* copyRandomList(Node* head) {
        //1.拷贝源节点并链接
        Node* cur = head;
        while(cur)
        {
            Node* copy = new Node(cur->val);
            copy->next = cur->next;
            cur->next = copy;
            cur = copy->next;
        }
        cur = head;
        //2.根据原节点,处理copy节点的random
        
        while(cur)
        {
            Node* copy = cur->next;
            if(cur->random == nullptr)
            {
                copy->random = nullptr;
            }
            else
            {
                copy->random = cur->random->next;
            }
            cur = copy->next;
        }
        cur = head;

        //3.把拷贝节点解下来,链接成新链表。同时恢复原链表;
        Node* copyhead, *copytail;
        copyhead = copytail = nullptr;
        while(cur)
        {
            Node* copy = cur->next;
            Node* next = copy->next;
            if(copytail == nullptr)
            {
                copyhead = copytail = copy;
            }
            else
            {
                copytail->next = copy;
                copytail = copy;
            }
            cur->next = next;
            cur = next;
        }
        return copyhead;
    }
};

 


http://www.niftyadmin.cn/n/23130.html

相关文章

python 时间

目录标题python的时间模块1、时间戳2、时间元组3、获取格式化的时间可以自定义输出格式日期格式化的符号4、显示某月的日历5、sleep模块python的时间模块 1、时间戳 时间戳,以1970为时间基准,但是太过于遥远的时间就不可以了,windows最源支持…

我亲身经历的2022年软件质量工作——测试工作的经验总结及一些建议

2022年对于大部分人来说都是辛苦的一年。对于整个社会,疫情反反复复,折磨的每一个人都心力交瘁。 经济下滑,失业率上升似乎听到的都是不好的消息。对于整个互联网行业也频频传出大厂裁员的消息。 而质量团队在大厂的裁员计划里也是首当其冲。…

VectorNet详解

Abstract 本篇论文主要做了三个方面的事情: 特征工程 不同与以前的方法,将车辆行驶收集的信息用一张全局的图像来表示,论文提出用向量表示车辆行驶过程中收集的各种信息。 2. 层次图神经网络 论文构建了一种层次图神经网络,层次,即首先各个实体比如车辆、红绿灯等…

Vue 中 CSS scoped 的原理

前言 在日常的Vue项目开发过程中&#xff0c;为了让项目更好的维护一般都会使用模块化开发的方式进行。也就是每个组件维护独立的template&#xff0c;script&#xff0c;style。主要介绍一下使用<style scoped>为什么在页面渲染完后样式之间并不会造成污染。 示例 搭…

Hex程序烧写到单片机

一、创建一个Keil代码工程 1、在电脑F盘&#xff08;哪个盘可以随意选择&#xff09;上创建项目工程文件夹Template 2、在Template文件中&#xff0c;创建一个main.c文件 3、进入keil主页面&#xff0c;工具栏project---->New uVision project---->选则第一步的工程文…

整理了上千个 Python 工具库,涵盖24个大方向

Python 生态&#xff0c;向来以各种类库齐全而闻名&#xff0c;这也是这门语言如此受欢迎的重要原因。 今天就给大家分享一下这几天的战果&#xff0c;宵衣旰食&#xff0c;不眠不休的整理了近千个 Python 库&#xff0c;梳理不易啊&#xff0c;收藏的同时&#xff0c;记得点赞…

c++语法欠缺地方

sizeof是用来计算变量占多大内存的&#xff0c;单位是字节&#xff08;byte&#xff09;&#xff1b;sizeof 后面跟类型时&#xff0c;必须加上括号&#xff0c;例如sizeof(double);后面跟变量可以不用加括号&#xff0c;例如&#xff1a;sizeof d%d是以十进制形式输出有符号整…

高并发内存池项目(C++实战项目)

文章目录&#x1f384;项目介绍◎项目来源▶项目源码◎内存池相关知识1、池化技术2、内存池3、内存池主要解决的问题4、malloc&#x1f384;设计思路◎第一阶段–设计一个定长的内存池适应平台的指针方案◎第二阶段–高并发内存池整体框架设计1.线程缓存&#xff08;thread cac…