• 【JAVA】链表面试题



    链表面试题

    加油学习!!冲冲冲呀!


    努力努力在努力!

    1. 删除链表中等于给定值 val 的所有节点。

    删除链表元素

    1. 思路:
      即removeAllKey()的代码:但是注意head是不可以加this的,因为该类实现的对象是通过后台进行传入的(注意部分进行修改)

    2. 代码:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode() {}
     *     ListNode(int val) { this.val = val; }
     *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
     * }
     */
    class Solution {
        public ListNode removeElements(ListNode head, int val) {
            // 其实就相当于实现removeAllKey
            // 加头结点or先处理后面的节点再处理头结点
    
            /* // 进来首先进行头结点是否为空的判断!!
            if(head == null) {
                return null;
            }
            // 需要一个循环:把整个链表都遍历完
            ListNode pre = head;
            ListNode cur = head.next; //自定义类型变量存储的是地址
            while (cur != null) {
                if(cur.val == val) {
                    pre.next = cur.next;
                    cur = cur.next;
                } else {
                    pre = cur;
                    cur = cur.next;
                }
            }
            // 单独处理头节点的问题,刚刚没有处理头节点问题!!
            if(head.val == val) { // 注意是if,不用while循环,因为上面已经处理了所有头结点之后的节点
                head = head.next;
            }
            // 注意把头结点的处理放在最后!!:因为如果是从头结点开始连续存在要删除的key值,头结点将会变换至下一个key,也就是会一直保留一个key在头结点位置
    */
    
            // 另一种方法是 创建一个新的头节点!!
            ListNode head1 = new ListNode(-1); // 随便存一个值就行
            head1.next = head;
            head = head1; // 注意此处的修改!
            // 然后进行遍历处理(不用单独考虑头结点)--上面方法
            ListNode pre = head;
            ListNode cur = head.next;
            while (cur != null) {
                if(cur.val == val) {
                    pre.next = cur.next;
                    cur = cur.next;
                } else {
                    pre = cur;
                    cur = cur.next;
                }
            }
            head = head.next;  // 注意要将头结点的位置进行变换!!
    
            return head;
        }
    }
    
    • 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

    2. 反转一个单链表。

    反转链表

    1. 思路:
    • (出现频率高)类似逆向进行存储,但是是原地反转:把头结点.next=null,然后将其他结点依次进行头插就行,需要再设置一个新的结点:Node curNext=cur.next; cur.next=head; head=cur; cur=curNext;在while(cur!=null)循环中进行实现
      (注意:要考虑只有一个结点和没有结点也就是null的情况!!)
    • head其实就是当前需要进行反转的节点的前驱
      (reverseList)
    1. 代码:
    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode() {}
     *     ListNode(int val) { this.val = val; }
     *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
     * }
     */
    class Solution {
        public ListNode reverseList(ListNode head) {
            // 考虑只有一个结点和没有结点的情况
            if(head == null) {
                return null;
            }
            if(head.next == null) {
                return head;
            }
    
            /* 以下是错误代码:
            ListNode curNext = head.next; //指向第二个结点
    
            // 因为头结点要变成尾结点,所以next进行置空
            head.next = null;
    
            // 其余结点进行头插:需要进行循环遍历链表实现
            while(curNext != null) {
                // 头插
                ListNode cur = head;
                head = curNext;
                head.next = cur;   // 此处也有问题:头结点的定义重要的不是变量head,而是指向性问题!!
                curNext = cur.next;  // 思路有问题!!
            }
            */
    
            // 更正代码:
            ListNode cur = head.next;  // 当前需要反转的节点,head是当前需要反转的节点的前驱!
            head.next = null; // 要变成尾结点
            while(cur != null) { // 进行遍历
                ListNode curNext = cur.next;
                cur.next = head;  // 注意此处逻辑!!!
                head = cur;
                cur = curNext;
            }
    
            return head;
    
        }
    }
    
    • 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

    3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

    链表的中间结点

    1. 思路:

    方法1:遍历一遍求长度,然后再遍历求中间结点(但是该方法至少要遍历1.5遍)
    方法2:要求只遍历一遍:使用快慢指针–slow所需时间是fast的两倍,则当fast走到末尾时,slow刚好走到中间位置!(但是奇偶数走到最后是有差异的,只要满足其中一个条件就说明fast走到了最后,但是如果两个条件只要其中一个不满足就说明是还没有到达末结点,需要继续走,其实一定要注意这里的逻辑符是
    逻辑与,只要一个不满足就false!!即:格外注意while循环的条件!!还有两个条件的顺序:fast在前!!:走了两步很可能先为空。

    1. 代码:
    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode() {}
     *     ListNode(int val) { this.val = val; }
     *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
     * }
     */
    class Solution {
        public ListNode middleNode(ListNode head) {
            // 首先判断是否为空
            if(head == null) {
                return null;
            }
    
            ListNode slow = head;
            // 注意此处错误!!快慢结点都应该从头结点开始!!
            //ListNode fast = head.next;
            ListNode fast = head;
            // 注意此处while语句的循环条件:只要一个不满足就说明已经走到了末指针,即false的短路-逻辑与
            // 注意两个表达式的顺序关系
            while(fast!=null && fast.next!=null) {
                fast = fast.next.next;
                slow = slow.next;
            }
            return slow;
    
            /*// 方法二:求长度+求中间值进行返回结点
            int count = 0;
            ListNode cur = head;
            while((size()/2) != count) { // 这里的话要新写size()方法
                cur = cur.next;
                count++;
            }
            return cur;*/
        }
    }
    
    • 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

    4. 输入一个链表,输出该链表中倒数第k个结点。

    链表中倒数第k个结点

    1. 思路:

    k进行合法性判断、
    方法1:遍历求长度、然后(长度-k)就是所要打印的节点,进行遍历就行
    方法2:要求只遍历一遍:使用快慢指针–相差(k-1)步,fast先走(k-1)步,然后slow与fast同时走,直到fast.next
    ==null才停止走!

    1. 代码:
    import java.util.*;
    /*
    public class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }*/
    public class Solution {
        public ListNode FindKthToTail(ListNode head,int k) {
            // 首先进行合法性判断
            if(k<0 || head == null) {
                return null;
            }
            ListNode fast = head;
            ListNode slow = head;
            //fast 先走k-1步 然后再一起走:要求是只遍历一遍
            while(k-1 != 0) { // 如果k超过长度,会空;但是k-1并不会==0而退出循环
                fast = fast.next; // 如果head为空,这里就是异常语句,所以要进行空指针判断!
                if(fast == null) {
                    return null; // k太大了就无输出!!
                }
                k--;  // 注意k要进行变换
            }
            // 同时走
            while(fast.next != null) {
                fast = fast.next;
                slow = slow.next;
            }
            return slow;
        }
    }
    
    • 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

    5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

    合并两个有序链表

    1. 思路:

    设置一个傀儡结点,然后两个链表的节点依次进行大小比较,串在傀儡结点之后(但是要注意判断两个头结点的情况)

    1. 代码:
    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode() {}
     *     ListNode(int val) { this.val = val; }
     *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
     * }
     */
    class Solution {
        public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
             // 新建一个虚拟结点
            ListNode newHead = new ListNode(-1); // 要让该结点保持不变,稍后好进行返回
            ListNode tmp = newHead;
            // 开始依次进行大小比较
            while(list1!=null && list2!=null) {
                if(list1.val > list2.val) {
                    tmp.next = list2;
                    list2 = list2.next;
                    tmp = tmp.next;
                } else {
                    tmp.next = list1;
                    list1 = list1.next;
                    tmp = tmp.next;
                }
            }
            // 出来则说明要么head1==null 要么head2==null (短路原则)
            if(list1==null) {
                tmp.next = list2;
            }
            if (list2==null) {
                tmp.next = list1;
            }
            return newHead.next;
        }
    }
    
    • 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

    6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 。

    链表分割

    1. 思路:

    进行一次遍历,然后把结点分别放在两个链表上(这两个链表就是以判断标识来进行区分的),然后结束后进行两个分链表的连接就行,然后把最后指向null(链表的话定义头尾结点就行)(插入方式是进行尾插)
    还要考虑一个问题:第一个段是否有结点满足! 把最后指向null是在存在后半段的情况下

    1. 代码:
    import java.util.*;
    
    /*
    public class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }*/
    public class Partition {
        public ListNode partition(ListNode pHead, int x) {
            // write code here
            // 分成两段:before 与 after (start & end)
            ListNode bs = null;
            ListNode be = null;
            ListNode as = null;
            ListNode ae = null;
            // 再创建一个临时结点表示当前结点位置
            ListNode cur = pHead;
    
            // 进行遍历
            while(cur != null) {
                if(cur.val<x) {
                    // 处于前半段
                    if(bs==null) {
                        // 说明现在是一个空结点
                        bs = cur;
                        be = cur;
                    } else {
                        be.next = cur;
                        be = be.next; //不要忘记!!
                    }
                } else {
                    // 处于后半段
                    if(as==null) {
                        // 说明现在是一个空结点
                        as = cur;
                        ae = cur;
                    } else {
                        ae.next = cur;
                        ae =ae.next;
                    }
                }
                cur = cur.next;
            }
            //如果前半段直接没有
            if(bs==null) {
                return as;
            }
            // 如果后半段存在
            if(ae!=null) {
                ae.next = null;
            }
            // 进行连接
            be.next = as;
            return bs;
        }
    }
    
    • 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

    7. 链表的回文结构。

    链表的回文结构

    1. 思路:

    回文结构:前后对称!
    要求空间复杂度O(1),但是前后同时遍历的思路是不可行的,因为是单向的
    解决:找中间位置、将中间之后的位置进行反转;然后就可以实现head往后走、slow往前走(快慢指针)(需要创建变量)
    注意赋值方式!!

    1. 代码:
    import java.util.*;
    
    /*
    public class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }*/
    public class PalindromeList {
        public boolean chkPalindrome(ListNode A) {
            // write code here
           // 找中间结点 + 中间之后进行反转 + 前后遍历 (会使用快慢指针)
    
            // 进行空判断
            if(A == null) {
                return true;
            }
    
            // 使用快慢指针找中间位置
            ListNode slow = A;
            ListNode fast = A;
            //while(fast != null) { // 注意这里条件!!!
            // 有奇偶之分,则最后判断条件也是不一样的,同时满足才进行,只要不满足一个就停止
            // 注意两个表达式的顺序!!!
            while (fast!=null && fast.next!=null) {
                fast = fast.next.next;
                slow = slow.next;
            }
            // 此时slow就是中间结点
            // 开始对中间结点之后的节点进行反转 + 建立变量
            ListNode cur = slow.next;
            while (cur != null) {
                ListNode curNext = cur.next;
                cur.next = slow;
                //slow = slow.next;// 注意此处是错误的 这样会造成一个循环
                slow = cur; // 直接这样子进行赋值,类似后面的赋值
                cur = curNext;
            }
            // 反转完毕 + 进行回文比较--head与slow分别进行前后遍历
            // 注意循环条件:考虑奇偶:只是简单的head!=slow 只能解决奇数问题,
            // 还有偶数问题就要另外考虑:head
            // 而偶数问题:head.next == slow 就是需要终止的时候了
            while(A!=slow ) {
                if(A.val != slow.val) {
                    return false;
                }
                // 在这里进行判断!!! 重要!!!
                if(A.next==slow) {
                    return true;
                }
                // 进行结点变换
                A = A.next;
                slow = slow.next;
            }
            // 来到这儿 说明正确
            return true;
        }
    }
    
    • 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

    8. 输入两个链表,找出它们的第一个公共结点。

    相交链表

    1. 思路:

    注意:两个链表相交是地址一样,而不是值一样!!!相交是一个Y字形
    思路:1.先求两个链表的长度
    2.计算两个链表的差值(创建两个变量,使得一个永远指向长的,另一个是短的)
    3.让最长的链表走差值步
    4.两个链表一起走,相遇的点就是相交点或者是没有相交点为null

    1. 代码:
    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
        public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            // 1. 求两个链表的长度
            int lengthA = 0;
            int lengthB = 0;
            // 创建两个变量,使之一直指向最长和最短链表,然后原来头结点就会保持不变
            ListNode nodeL = headA; // long
            ListNode nodeS = headB; // short
            while(nodeL!=null) {
                lengthA++;
                nodeL=nodeL.next;
            }
            while (nodeS!=null) {
                lengthB++;
                nodeS = nodeS.next;
            }
            // 注意要执行后面的各条语句 一定要先把nodeL/S处于头结点的位置上!!
            //而此时并没有在头结点处 所以执行后面语句!!!
            nodeL = headA;
            nodeS = headB;
            // 2. 进行长度比较 + 最长最短的变换
            int len = lengthA-lengthB;
            if(len<0) {
                nodeL = headB;
                nodeS = headA;
                len = lengthB-lengthA;
            }
            
            // 3. 长的先走差值步
            while(len!=0) {
                nodeL = nodeL.next;
                len--;
            }
    
            // 4. 两个链表同时走
            // 这里写法有问题,就会缺少返回值
            /*while(nodeL!=null) {
                if(nodeL==nodeS) {
                    return nodeL;
                }
                nodeL = nodeL.next;
                nodeS = nodeS.next;
            }*/
            // 注意这个还可以再进行修改:还可以更加简便!
            /*while(nodeL!=nodeS && nodeL!=null) { //如果等于就是相交
                nodeL = nodeL.next;
                nodeS = nodeS.next;
            }
            if (nodeS==null) {
                return null;
            }*/
            while(nodeL!=nodeS ) { //如果等于时要么是相交 要么是二者都已经走完为空
                nodeL = nodeL.next;
                nodeS = nodeS.next;
            }
            // 此时来到这里,要么找到交点 要么是遍历完为null,
            // 不管哪种情况都是二者相等的时候,所以随便输出那个都行,况且也不用进行判断
            return nodeL;
        }
        
    }
    
    • 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

    9. 给定一个链表,判断链表中是否有环。

    环形链表

    1. 思路:

    环一定是最后一个又指向之前的某一个,所以有环链表中是不存在null的;不可能是中间的某一个又指向之前的某一个,因为一个结点只能存储一个地址
    – 思路:使用快慢指针,快慢指针是有速度差的(那么重点来了:为什么slow走一步 fast走两步,而不是fast走其他步数呢? 这是一个追击问题,最坏的情况是快慢指针相差一圈,而一次两步即使是在最坏情况下也是最多走一圈就可以追上,不会存在套圈问题。(如果环是2个,走3步就会迎来擦肩而过的问题)
    – 如果fast或者fast.next==null,就说明不存在环(考虑奇偶问题,所以null有两种情况)
    – 每次走完都判断一下是否相等

    1. 代码:
    /**
     * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
        public boolean hasCycle(ListNode head) {
            // 快慢指针
            ListNode fast = head;
            ListNode slow = head;
            // 循环判断是否有环 如果相遇就说明有环 如果其中一个(fast or fast.next)是null就说明不存在环
            // 环是没有null的
            /*while(fast.next!=null && fast!=null) { //注意这里的顺序是错误的!!!!!
                fast = fast.next.next;  //一次走两步
                slow = slow.next;
                // 放在后面而不是前面的原因,环至少都有两个结点!!
                if(fast == slow) {
                    return true;
                }
            }
            // 出来就说明遇到了null
            return false;*/
    
            // 可以修改如下;
            while( fast!=null && fast.next!=null ) { // 注意顺序,只有fast补null才有next
                fast = fast.next.next;  //一次走两步
                slow = slow.next;
                if(fast == slow) {
                    break;
                }
            }
            // 出来有两种情况:要么遇到null 要么相等 进行判断
            // 然后一定要注意这里的判断使用声明进行判断,用是否为null是因为要考虑一个结点的情况:
            // 一个结点时并不是环,环至少要两个结点,如果是用地址相等判断就会为真,
            // 但是实际上是假的,因为while循环的条件中满足其中一个为假直接出来应该为假
            /*if(fast == slow) {
                return true;
            }
            return false;*/
            // 所以进行修改如下:
            if(fast==null || fast.next==null) {  // 只要一个为真就是真 所以要注意逻辑
                return false;
            }
            return true;
        }
    }
    
    • 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

    10. 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL。

    环形链表II

    1. 思路:

    原理:设起始点到入口点的距离为x,设相遇点到入口点的长度为y,环的长度为C;
    在相同时间内,fast速度是slow的2倍,则fast路程也是slow的两倍:x=y时就是时就可以找到入口点
    so:当找到相遇点后 将其中一个指针移到头结点位置,两种=者再以相同的速度走,当二者相等时就是入口点位置。
    (注:即使是fast转了好多圈也是一样的情况,slow只走一圈;然后转圈越多说明环越小)

    原理

    1. 代码:
    /**
     * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
        public ListNode detectCycle(ListNode head) {
            // 先判断有无环:使用快慢指针 +是否相等or遇到null(循环条件)
            ListNode fast = head;
            ListNode slow = head;
            while(fast!=null && fast.next!=null) {
                fast = fast.next.next;
                slow = slow.next;
                // 进行判断
                if(slow==fast) {
                    break;
                }
            }
            // 出来就说明要么==null 要么相等
            if(fast==null || fast.next==null) {
                return null;
            }
    
            // 如果有环在进行前后同时走相遇的操作:走到这里就说明有环,且此时相遇
            slow = head;
            while(slow!=fast) {
                slow = slow.next;
                fast = fast.next;
            }
            return slow;
        }
    }
    
    • 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

    11. 其他练习。

    力扣链表 + 牛客网


    THINK

    注意习题的练习!思路以及逻辑!
    还有快慢指针的使用!!!

  • 相关阅读:
    自学设计模式
    使用 Burpsuite 与 xray 进行联动
    ceph 010 clustermap ceph调优
    【精讲】vue v-if的demo案例、v-show案例、v-for循环遍历案例
    Python制定高级期权交易策略:技术和定量分析综合指南
    超详细-Vivado配置Sublime+Sublime实现VHDL语法实时检查
    c++ openssl实现https
    【区块链 | DAPP】React版Dapp开发模板(连接钱包、合约调用全流程和一个批量转账工具实战)
    零基础学Java(3)运算符
    【ERROR】MySQL太多连接数,导致阻塞
  • 原文地址:https://blog.csdn.net/weixin_54150521/article/details/126140925