优选算法——链表

1. 链表常用技巧和操作总结

2. 两数相加

题目链接2. 两数相加 - 力扣(LeetCode)

题目展示

题目分析:本题给的是逆序,其实降低了难度,逆序刚好我们从第一位开始加,算法原理其实就是模拟相加的过程。

代码实现

复制代码
/**
 * 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* addTwoNumbers(ListNode* l1, ListNode* l2) 
    {
        ListNode* cur1=l1,*cur2=l2;
        ListNode* newnode=new ListNode(0);//创建虚拟头节点
        ListNode* prev=newnode;
        int t=0;//记录进位
        while(cur1||cur2||t)
        {
            if(cur1)
            {
                t+=cur1->val;
                cur1=cur1->next;
            }
            if(cur2)
            {
                t+=cur2->val;
                cur2=cur2->next;
            }
        prev->next=new ListNode(t%10);
        prev=prev->next;
        t/=10;
        }
        prev=newnode->next;
        delete newnode;
        return prev;
    }
};

3. 两两交换链表中的结点

题目链接24. 两两交换链表中的节点 - 力扣(LeetCode)

题目展示

题目分析:本题我们就需要用到前面提到的技巧来解决,即创建虚拟头节点。

我们创建完虚拟头节点后,访问节点就会很方便;还有一点,就是我们不要吝啬空间,大胆地去定义变量。正如此题,我们想实现交换操作,涉及4个节点之间的变换,如果我们不定义变量去标记,那么指针的变换将会很复杂,容错率就会大大降低。

代码实现

复制代码
/**
 * 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=new ListNode(0);
        newHead->next=head;
        //定义变量来标记
        ListNode* prev=newHead,*cur=prev->next,*next=cur->next,*nnext=next->next;
        while(cur&&next)
        {
            //交换节点
            prev->next=next;
            next->next=cur;
            cur->next=nnext;
            //修改指针(顺序不能改)
            prev=cur;
            cur=nnext;
            if(cur)
            {
                next=cur->next;
            }
            if(next)
            {
                nnext=next->next;
            }
        }
        cur=newHead->next;
        delete newHead;
        return cur;
    }
};

大家能够看到,根据上面的图加上我们定义的变量,代码的逻辑是很清晰的,大家需要注意一些特殊情况的处理,以免造成程序崩了。

4. 重排链表

题目链接143. 重排链表 - 力扣(LeetCode)

题目展示

题目分析:本题大家一定要画图分析,找到其中的规律,其实本题是我们之前学过的三道题的综合。

代码实现

在实现之前,我们先来明确一个问题,大家来看下图:

大家可以看到,进行逆序操作时,有两种做法,这两种方法其实殊途同归,都可以实现逆序的操作,这里我更推荐大家用第一种,即让slow后面的节点进行逆序。

复制代码
​
/**
 * 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:
    void reorderList(ListNode* head) 
    {
        //处理边界情况
        if(head==nullptr||head->next==nullptr||head->next->next==nullptr)
        {
            return;
        }
        //1. 找到链表的中间节点
        ListNode* fast=head;
        ListNode* slow=head;
        while(fast&&fast->next)
        {
            slow=slow->next;
            fast=fast->next->next;
        }
        //2. 将slow后面的部分进行逆序操作------头插法
        ListNode* head2=new ListNode(0);
        ListNode* cur=slow->next;
        slow->next=nullptr;//断开两个链表
        while(cur)
        {
            ListNode* next=cur->next;
            cur->next=head2->next;
            head2->next=cur;
            cur=next;
        }
        //3.合并两个链表
        ListNode* ret=new ListNode(0);
        ListNode* prev=ret;
        ListNode* cur1=head,*cur2=head2->next;
        while(cur1)
        {
            //先放第一个链表------尾插
            prev->next=cur1;
            prev=prev->next;
            cur1=cur1->next;
            //再放第二个链表
            if(cur2)
            {
                prev->next=cur2;
                prev=prev->next;
                cur2=cur2->next;
            }
        }
    }
};

​

这里大家注意代码的逻辑,对应题目分析中的图,找中间节点------快慢指针,逆序操作------头插法,合并链表------双指针。

5. 总结

本篇博客为大家介绍了几个链表的题目,之前在学习链表的时候也总结了一些题,具体大家有兴趣可以去看这两篇:单链表的应用-CSDN博客链表OJ题-CSDN博客。最后希望以上内容可以为大家带来帮助,感谢阅读!

相关推荐
To_OC7 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
旖-旎8 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
To_OC8 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
delishcomcn9 小时前
AI视觉识别+分切算法:电化铝缺陷检测与裁切一体化解锁
人工智能·算法
触底反弹9 小时前
深入理解大模型采样:Temperature、Top-K、Top-P 的原理与实战
人工智能·算法·面试
雪碧聊技术10 小时前
力扣 LCR 091. 粉刷房子 —— 动态规划入门详解
算法·动态规划
延凡科技12 小时前
多场景落地复盘:端边云架构无人机智能巡检系统设计与实践
大数据·数据结构·人工智能·科技·架构·无人机·能源
CV-Climber13 小时前
检索技术的实际应用
人工智能·算法
hhzz13 小时前
Tiger AI Platform平台中增加人脸识别功能
图像处理·人工智能·算法·计算机视觉·大模型