• LeetCode链表集锦


    在这里插入图片描述

    ⭐️前言⭐️

    本篇文章是博主按照代码随想录的链表部分力扣题的一些见解,有一些自己的想法与代码随想录题解结合,能使这部分题理解的更加透彻。

    🍉博客主页: 🍁【如风暖阳】🍁
    🍉精品Java专栏【JavaSE】【备战蓝桥】、【JavaEE初阶】【MySQL】【数据结构】
    🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

    🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉

    🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

    🍉博客中涉及源码及博主日常练习代码均已上传码云(gitee)GitHub


    🍅203.移除链表元素

    力扣题目链接

    题意:删除链表中等于给定值 val 的所有节点。

    示例 1:
    输入:head = [1,2,6,3,4,5,6], val = 6
    输出:[1,2,3,4,5]

    示例 2:
    输入:head = [], val = 1
    输出:[]

    示例 3:
    输入:head = [7,7,7,7], val = 7
    输出:[]

    思路:

    在这里插入图片描述
    设置虚拟头节点,让del节点从头开始遍历,找到相应定值对应的点后完成删除。
    完成删除操作使用双指针的方法,前后两个节点紧挨着一步一步往后走,如果找到对应删除节点就让删除的节点的前一个节点的next域跳两步,最后完成遍历后返回虚拟头节点的next域(这才是新的头节点)

    代码:

    class Solution {
        public ListNode removeElements(ListNode head, int val) {
            if(head==null) {
                return null;
            }
            ListNode dummyNode=new ListNode();
            dummyNode.next=head;
            ListNode ahead=dummyNode;
            ListNode cur=head;
            while(cur!=null) {
                if(cur.val==val) {
                    ahead.next=cur.next;
                    cur=cur.next;
                }else {
                    cur=cur.next;
                    ahead=ahead.next;
                }
            }
            return dummyNode.next;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    🍅707. 设计链表

    力扣题目链接

    题意:

    在链表类中实现这些功能:

    get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
    addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
    addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
    addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
    deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

    思路:
    具体思路在代码注释中体现。

    代码:

    //定义节点
    class Node {
        int val;
        Node next;
        public Node(int val) {
            this.val=val;
        }
    }
    class MyLinkedList {
        int val;
        Node head;
        public MyLinkedList() {
        }
        
        //该方法用于返回链表长度
      	private int size() {
            int count=0;
            Node cur=head;
            while(cur!=null) {
                count++;
                cur=cur.next;
            }
            return count;
        }
        //get(index)
        public int get(int index) {
        //如果下标不合法返回-1
            if(index<0||index>=size())
                return -1;
            Node cur=this.head;
            int count=0;
            while(count!=index) {
                cur=cur.next;
                count++;
            }
            return cur.val;
        }
        //头插
        public void addAtHead(int val) {
            Node node=new Node(val);
            if(head==null) {
                head=node;
                return;
            }
            node.next=this.head;
            this.head=node;
        }
        //尾插
        public void addAtTail(int val) {
            Node node=new Node(val);
            if(head==null) {
                head=node;
                return;
            }
            Node cur=this.head;
            while(cur.next!=null) {
                cur=cur.next;
            }
            cur.next=node;
        }
        //返回对应下标的前一个节点
        private Node searchIndex(int index) {
            Node cur=this.head;
            int count=0;
            while (count!=index-1) {
                count++;
                cur=cur.next;
            }
            return cur;
        }
        //指定下标插入
        public void addAtIndex(int index, int val) {
       		 //下标<=0 头插
            if(index<=0) {
                addAtHead(val);
                return;
            }
            //下标等于链表长度 尾插
            if(index==size()) {
                addAtTail(val);
                return;
            }
            //下标大于链表长度 直接返回
            if(index>size())
                return;
            //找到指定下标的前一个节点,插入新的节点
            Node cur=searchIndex(index);
            Node node=new Node(val);
            //新节点后后边节点连接
            node.next=cur.next;
            //前一个节点和新节点连接
            cur.next=node;
        }
        //删除指定位置节点
        public void deleteAtIndex(int index) {
        	//不合法直接返回	
            if (index < 0 || index >= size()) {
                return;
            }
            //下标为0删除头节点
            if(index==0) {
                head=head.next;
            }else {
            //其他情况还是找到删除节点的前一个节点,让其next域跳两次完成删除
                Node cur=searchIndex(index);
                cur.next=cur.next.next;
            }
        }
    }
    
    /**
     * Your MyLinkedList object will be instantiated and called as such:
     * MyLinkedList obj = new MyLinkedList();
     * int param_1 = obj.get(index);
     * obj.addAtHead(val);
     * obj.addAtTail(val);
     * obj.addAtIndex(index,val);
     * obj.deleteAtIndex(index);
     */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    🍅206.反转链表

    力扣题目链接
    题意:反转一个单链表。

    示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL

    思路:

    在这里插入图片描述
    完成倒置,就需要将每个节点的next域指向前一个节点,但如果发生改变就找不到后一个节点了,所以需要找一个临时节点进行存储,然后再进行修改。

    代码:
    双指针:

    class Solution {
        public ListNode reverseList(ListNode head) {
            if(head==null||head.next==null)
            return head;
            //前一个节点
            ListNode prev=null;
            //反转节点
            ListNode cur=head;
            //临时节点,用于存储cur节点的下一个节点
            ListNode curNext=null;
            while(cur!=null) {
            	//临时节点先进行存储
                curNext=cur.next;
                //当前节点的next指向前一个节点
                cur.next=prev;
                //前一个节点后移
                prev=cur;
                //当前节点后移
                cur=curNext;
            }
            //最后全部反转完成后,prev节点就是反转后链表的头节点
            return prev;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    递归:

    class Solution {
        public ListNode reverseList(ListNode head) {
        	//传递的两个参数就是需要反转的两个节点
            return reverse(null,head);
        }
        private ListNode reverse(ListNode prev,ListNode cur) {
            if(cur==null)
            return prev;
            ListNode curNext=cur.next;
            cur.next=prev;
            prev=cur;
            cur=curNext;
            //完成后移以后递归新的反转节点
            return reverse(prev,cur);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    🍅24. 两两交换链表中的节点

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

    在这里插入图片描述
    思路:
    在这里插入图片描述

    代码:

    class Solution {
        public ListNode swapPairs(ListNode head) {
            ListNode dummyNode=new ListNode(0);
            dummyNode.next=head;
            ListNode cur=dummyNode;
            //需要交换这两个节点的顺序,所以这两个节点都不能为空
            while(cur.next!=null&&cur.next.next!=null) {
            	//先对这两个节点地址进行存储
                ListNode node1=cur.next;
                ListNode node2=cur.next.next;
                cur.next=node2;
                node1.next=node2.next;
                node2.next=node1;
                //最后把cur节点移到下一次两个交换节点的前一个节点
                cur=node1;
            }
            return dummyNode.next;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    🍅19. 删除链表的倒数第 N 个结点

    力扣题目链接
    题意
    给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
    在这里插入图片描述
    输入:head = [1,2,3,4,5], n = 2
    输出:[1,2,3,5]

    思路:
    快慢指针,快指针先走一定步数,然后快慢指针一起走,当快指针走出链表为null时,慢指针走到倒数第n+1个节点的位置,让其next域跳两步完成删除

    代码:

    class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode dummy=new ListNode(-1);
            dummy.next=head;
            ListNode slow=dummy;
            ListNode fast=dummy;
            while(n+1>0) {
                fast=fast.next;
                n--;
            }
            while(fast!=null) {
                slow=slow.next;
                fast=fast.next;
            }
            slow.next=slow.next.next;
            return dummy.next;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    🍅面试题 02.07. 链表相交

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

    图示两个链表在节点 c1 开始相交:
    在这里插入图片描述

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

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

    示例 1:
    在这里插入图片描述

    示例 2:
    在这里插入图片描述

    示例 3:

    在这里插入图片描述

    思路:
    先对两个链表都完成一次遍历,计算其链表长度,让长的链表头先走两链表之差步,然后两个指针再一起走,第一次next域相同时就是相交处,如果没有相同一直走到空,说明不相交。

    代码:

    public class Solution {
        public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            int countA=count(headA);
            int countB=count(headB);
            int a=countA-countB;
            ListNode curA=new ListNode(0);
            curA.next=headA;
            ListNode curB=new ListNode(-1);
            curB.next=headB;
            if(a>0) {
                while(a-->0)
                curA=curA.next;
            }else {
                a=-a;
                while(a-->0)
                curB=curB.next;
            }
            while(curA!=null&&curB!=null) {
                if(curA.next==curB.next) {
                    return curA.next;
                }
                curA=curA.next;
                curB=curB.next;
            }
            return null;
        }
        private int count(ListNode head) {
            ListNode cur=head;
            int count=0;
            while(cur!=null) {
                count++;
                cur=cur.next;
            }
            return count;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    🍅142. 环形链表 II

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

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

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

    在这里插入图片描述
    思路:

    做这道题需要考虑两个事情:

    • 链表是否有环
    • 环的入口在哪里

    1、判断有环
    定义快慢指针从链表头开始走,快指针每次走两步,慢指针每次走一步,如果有指针走出去为null则一定无环,如果有环则快慢指针一定会相遇。
    为什么如果有环快慢指针一定会相遇呢?
    快指针先入环,无论慢指针入环时快指针在环的哪个位置,两者的相对速度差一,快指针每次都会靠近慢指针一步,一定会相遇。

    2.寻找环的入口
    在这里插入图片描述
    快指针是慢指针速度的两倍,所以慢指针走一圈快指针就会走两圈,又因为由1中分析,两者以相对速度为一的速度靠近,则一定不会错过(一定相遇),所以慢指针入环后,走不完第一圈就一定会被快指针赶上(快指针也走不完两圈)。
    slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A,由此可以得出两者的路程关系等式。

    2*(x+y)=x+y+n(y+z)

    又由前边分析得,慢指针走不完一圈会被快指针追上,则快指针也走不完两圈,所以n为1
    由此得x=z。
    这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。

    代码:

    public class Solution {
        public ListNode detectCycle(ListNode head) {
            if(head==null||head.next==null)
            return null;
            ListNode fast=head;
            ListNode slow=head;
            while(fast!=null&&fast.next!=null) {
                fast=fast.next.next;
                slow=slow.next;
                if(fast==slow) {
                    fast=head;
                    while(fast!=slow) {
                        fast=fast.next;
                        slow=slow.next;
                    }
                    return fast;
                }
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    🍅导图总结

    在这里插入图片描述


    ⚡️最后的话⚡️

    总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁
    在这里插入图片描述

  • 相关阅读:
    使用transformers进行端到端的目标检测
    GB4806.7食品级塑料包装袋进出口监管要求
    mysql 每日自动备份数据库
    【解决问题】部署在云服务器、Liunx的项目/jar包/业务服务,其他服务器、本地无法请求无法访问请求404请求报错
    【软件工具】PM2的常用命令
    初始Spring MVC
    conntrack最大数量
    gzip 压缩优化大 XML 响应的处理方法
    Setup exvim enviroment
    Linux进程概念(一)
  • 原文地址:https://blog.csdn.net/qq_60856948/article/details/125597180