【算法刷题之链表篇(1)】

这篇具有很好参考价值的文章主要介绍了【算法刷题之链表篇(1)】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.leetcode-82. 删除排序链表中的重复元素 II

(1)题目描述

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
【算法刷题之链表篇(1)】,算法,链表,数据结构

(2)方法及思路(一次遍历)

1.我们从指针 prev 指向链表的哑节点,随后开始对链表进行遍历。
2.如果当前 cur与 cur.next对应的元素相同,那么我们就需要将 cur 以及所有后面拥有相同元素值的链表节点全部删除。
3.我们记下这个元素值 ,随后不断将 cur从链表中移除
4.如果cur与cur->next对应的元素不相同,则将prev指向cur所在位置,cur继续往下找。
5.当遍历完整个链表之后,我们返回链表的的哑节点的下一个节点 dummy.next即可。
注意:哑节点可以不用考虑head就被删的特殊情况

(3)代码实现

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head==NULL)
        {
            return NULL;
        }
        ListNode* newnode=new ListNode(0);
        ListNode* prev=newnode;
        prev->next=head;
        ListNode* cur=head;
        while(cur!=NULL&&cur->next!=NULL)
        {
            if(cur->val==cur->next->val)
            {
                int val=cur->val;
                while(cur != NULL && cur->val == val){
                    cur = cur->next;
                }
                prev->next=cur;
            }
            else
            {
                prev=cur;
                cur=cur->next;
            }
        }
        return newnode->next;
    }
};

2.leetcode-19. 删除链表的倒数第 N 个结点

(1)题目描述

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
【算法刷题之链表篇(1)】,算法,链表,数据结构

(2)方法一:双指针

思路
1.先定义一个first指针,由于要删掉倒数第n个节点,所以可以让first指针先走n步。
2.当first走完,在定义一个second指针,此时两指针一起走,当first走到尾部时,second就走到了要删掉的节点的前一位。
3.将second所在节点指向它下一位的下一位,即可删掉
注意点:first和second从哪里开始走?first的终止条件是哪里?
first从head出发,终止条件是走到空停止,
而对于second与第一题中一样,引入哑节点,second从此处开始走

代码实现

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* newnode=new ListNode(0,head);
        ListNode* cur=head;
        while(n>0)
        {
            cur=cur->next;
            n--;
        }
        ListNode* prev=newnode;
        while(cur)
        {
            prev=prev->next;
            cur=cur->next;
        }
        prev->next=prev->next->next;
        return newnode->next;
    }
};

(3)方法二:计算链表长度(最直观)

思路:
一种容易想到的方法是,我们首先从头节点开始对链表进行一次遍历,得到链表的长度 L。随后我们再从头节点开始对链表进行一次遍历,当遍历到第 L−n+1 个节点时,它就是我们需要删除的节点。
代码实现

class Solution {
public:
    int getLength(ListNode* head) {
        int length = 0;
        while (head) {
            ++length;
            head = head->next;
        }
        return length;
    }

    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);
        int length = getLength(head);
        ListNode* cur = dummy;
        for (int i = 1; i < length - n + 1; ++i) {
            cur = cur->next;
        }
        cur->next = cur->next->next;
        ListNode* ans = dummy->next;
        delete dummy;
        return ans;
    }
};

(4)方法三:栈

思路:
我们也可以在遍历链表的同时将所有节点依次入栈。根据栈「先进后出」的原则,我们弹出栈的第 n 个节点就是需要删除的节点,并且目前栈顶的节点就是待删除节点的前驱节点。这样一来,删除操作就变得十分方便了。(也就是只要找到就直接操作)
代码实现

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);
        stack<ListNode*> stk;
        ListNode* cur = dummy;
        while (cur) {
            stk.push(cur);
            cur = cur->next;
        }
        for (int i = 0; i < n; ++i) {
            stk.pop();
        }
        ListNode* prev = stk.top();
        prev->next = prev->next->next;
        ListNode* ans = dummy->next;
        delete dummy;
        return ans;
    }
};

3.leetcode-83. 删除排序链表中的重复元素

(1)题目描述

给定一个已排序的链表的头 head ,删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
【算法刷题之链表篇(1)】,算法,链表,数据结构

(2)方法及思路(一次遍历)

思路:具体地,我们从指针 cur\textit{cur}cur 指向链表的头节点,随后开始对链表进行遍历。如果当前 cur 与 cur.next 对应的元素相同,那么我们就将 cur.next 从链表中移除;否则说明链表中已经不存在其它与 cur 对应的元素相同的节点,因此可以将 cur 指向 cur.next。

(3)代码实现

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (!head) {
            return head;
        }

        ListNode* cur = head;
        while (cur->next) {
            if (cur->val == cur->next->val) {
                cur->next = cur->next->next;
            }
            else {
                cur = cur->next;
            }
        }

        return head;
    }
};

4.leetcode-86. 分隔链表

(1)题目描述

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
【算法刷题之链表篇(1)】,算法,链表,数据结构

(2)方法及思路(模拟)

思路
直观来说我们只需维护两个链表 small 和 large 即可,small 链表按顺序存储所有小于 x 的节点,large 链表按顺序存储所有大于等于 x的节点。遍历完原链表后,我们只要将 small 链表尾节点指向 large 链表的头节点即能完成对链表的分隔。
1.先定义两个哨兵位smallHead和largeHead这样做的目的是为了更方便地处理头节点为空的边界条件。
2.遍历链表,找出小的储存进small,大的储存进large
3.合并链表时注意large节点的指向,并注意要删除largeHead

(3)代码实现

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode* small=new ListNode(0);
        ListNode* smallHead=small;
        ListNode* large=new ListNode(0);
        ListNode* largeHead=large;
        while(head!=NULL)
        {
            if(head->val<x)
            {
                small->next=head;
                small=small->next;
            }
            else
            {
                large->next=head;
                large=large->next;
            }
            head=head->next;
        }
        large->next=NULL;
        small->next=largeHead->next;
        delete largeHead;
        return smallHead->next;
    }
};

5.leetcode-25. K 个一组翻转链表(较难)

(1)题目描述

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
【算法刷题之链表篇(1)】,算法,链表,数据结构

(2)方法及思路(模拟)

思路
1.首先按照k来进行分组,每k个会重新是一个head。
2.然后对每k个数进行反转链表。
3.反转完链表,要注意头和尾与前后的相连,所以在实现反转链表的函数中还要返回头和尾
4.遍历到最后时,如果个数少于k就直接返回
【算法刷题之链表篇(1)】,算法,链表,数据结构

(3)代码实现

首先先实现部分链表反转部分

    pair<ListNode*,ListNode*> myReserve(ListNode* head,ListNode* tail)
    {
        ListNode* prev=tail->next;
        ListNode* p=head;
        while(prev!=tail)
        {
            ListNode* nex=p->next;
            p->next=prev;
            prev=p;
            p=nex;
        }
        return {tail,head};
    }

总体部分实现
1.在每次实现完注意要有个prev在head前,一开始就是哨兵位,prev用来与反转完的部分进行连接。prev更新的位置即使在tail处(新head前)
2.还要定义一个next在反转链表之前,也就是在找到新tail时定义在他的后面,用于反转部分尾部的连接文章来源地址https://www.toymoban.com/news/detail-662036.html

ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* hair=new ListNode(0);
        hair->next=head;
        ListNode* pre=hair;
        while(head)
        {
            ListNode* tail=pre;
               for (int i = 0; i < k; ++i) {
                tail = tail->next;
                if (!tail) {
                    return hair->next;
                }
            }
            ListNode* next=tail->next;
            pair<ListNode*,ListNode*> result=myReserve(head,tail);
            head=result.first;
            tail=result.second; 
            pre->next=head;
            tail->next=next;
            pre=tail;
            head=tail->next;
        }
        return hair->next;
    }

到了这里,关于【算法刷题之链表篇(1)】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法与数据结构之链表

    链表的定义,相信大家都知道,这里就不赘述了只是链表分单向链表和双向链表,废话不多说,直接上代码 链表节点的定义: 打印链表的两种方式: 翻转单向链表:核心思路是先断开连接,再将next指向前继节点,为了避免断开之后,找不到前继节点,需要用一个临时变量记

    2024年02月05日
    浏览(50)
  • 算法刷题营【Day3】:: 链表篇:单链表结点删除思路:一题辨别哨兵结点的优势(删除有奇效):203. 移除链表元素

    本内容是笔者结合《代码随想录》总结所得,记录学习过程,分享知识! 目录: 1. 开篇例题:203. 移除链表元素 2. 题解参考 - - 2.1 方法一:原表操作(不含哨兵结点) - - 2.2 方法二:虚设哨兵结点辅助法 - - 2.3 方法三:递归法 3. 单链表结点删除思路 4. 方法思路点拨:原表操

    2024年02月06日
    浏览(48)
  • 数据结构之链表

    头文件 自定义函数 主函数 效果图  

    2024年01月25日
    浏览(50)
  • 数据结构之链表详解

    链表是一种常见的数据结构,它可以用来存储一组数据,并支持快速的插入和删除操作。相比于数组,链表的大小可以动态地增加或减小,因此在某些场景下更加灵活和高效。本文将详细介绍链表的定义、基本操作和应用场景,希望能够帮助读者深入理解链表的原理和实现。

    2024年02月03日
    浏览(50)
  • 【数据结构】线性表之链表

    上一篇文章讲述了线性表中的顺序表,这篇文章讲述关于链表的定义、类别、实现、多种不同链表的优缺点和链表与顺序表的优缺点。 关于上一篇文章的链接:线性表之顺序表 链表是一种物理存储结构上 非连续、非顺序 的存储结构,数据元素的逻辑顺序是通过链表中的指针

    2024年02月05日
    浏览(59)
  • C语言数据结构之链表

    在上一篇博客中我们提到,线性表包括顺序表和链表,顺序表在上篇博客中已经介绍,本篇博客介绍一下另一种线性表—— 链表 。 概念:链表是⼀种 物理存储结构上⾮连续、⾮顺序 的存储结构,数据元素的 逻辑顺序是通过链表中的指针链接次序实现的 。 链表的结构跟⽕

    2024年04月22日
    浏览(44)
  • C++数据结构之链表(详解)

    主要参考文章地址 01.链表基础知识 | 算法通关手册 (itcharge.cn)) 本次内容是对链表的总结,可以看了上面的文章之后。 在看我下面的内容,做一个简短的复习,且本内容的代码均用C++实现,而参考资料的代码则为python。 每一个标题都有一个完整的链接,也可以点击下面的链

    2024年02月15日
    浏览(76)
  • C语言进阶——数据结构之链表(续)

    hello,大家好呀,我是Humble,本篇博客承接之前的 C语言进阶——数据结构之链表 的内容 (没看过的小伙伴可以从我创建的专栏C语言进阶之数据结构 找到那篇文章并阅读后在回来哦~) ,上次我们重点说了链表中的 单链表 ,即 不带头单向不循环链表 还说到了链表的分类虽

    2024年01月25日
    浏览(59)
  • 数据结构之链表练习与习题详细解析

    个人主页:点我进入主页 专栏分类:C语言初阶      C语言程序设计————KTV       C语言小游戏     C语言进阶 C语言刷题       数据结构初阶 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂。 目录 1.前言 2.习题解析 2.1习题一 2.2习题二 2.3习题三 2.4习题四 2.

    2024年02月05日
    浏览(45)
  • 【023】C/C++数据结构之链表及其实战应用

    💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。 👉 🎖️ CSDN实力新星,社区专家博主 👉 🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、

    2024年02月08日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包