优选算法——链表

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博客。最后希望以上内容可以为大家带来帮助,感谢阅读!

相关推荐
学编程的小程7 分钟前
LeetCode216
算法·深度优先
leeyayai_xixihah7 分钟前
2.21力扣-回溯组合
算法·leetcode·职场和发展
01_9 分钟前
力扣hot100——相交,回文链表
算法·leetcode·链表·双指针
萌の鱼10 分钟前
leetcode 2826. 将三个组排序
数据结构·c++·算法·leetcode
Buling_011 分钟前
算法-哈希表篇08-四数之和
数据结构·算法·散列表
AllowM12 分钟前
【LeetCode Hot100】除自身以外数组的乘积|左右乘积列表,Java实现!图解+代码,小白也能秒懂!
java·算法·leetcode
RAN_PAND38 分钟前
STL介绍1:vector、pair、string、queue、map
开发语言·c++·算法
左灯右行的爱情3 小时前
Redis数据结构总结-listPack
数据结构·数据库·redis
fai厅的秃头姐!3 小时前
C语言03
c语言·数据结构·算法
醉城夜风~3 小时前
[数据结构]单链表详解
数据结构·链表