当前位置: 首页 > news >正文

链表相关练习--2

目录

1、链表分割

2、找出两个链表的公共结点

3、判断链表是否有环

4、找到有环链表的入口点


1、链表分割

牛客:链表分割_牛客题霸_牛客网

思路:

1. 遍历链表,小于 x 的放到一起,大于等于x的放到一起,分成两段链表

2. 不改变原有顺序,需要使用尾插法

3. 最后把两段链表穿起来,返回第一段链表的首节点即可

4. 考虑特殊情况,所有节点都是 >= x 的,也就是说前半段链表是空,结点都在后半段,此时需再加一个第一个区间没有数据的语句

5. 注意,若第二个区间有数据,需要把第二个区间的最后一个结点的 next 置空,否则可能会出现死循环的错误

    public ListNode partition(ListNode pHead, int x) {
        if(pHead == null) {
            return null;
        }

        ListNode bs = null;
        ListNode be = null;

        ListNode as = null;
        ListNode ae = null;

        // cur 用于遍历链表
        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;
        }
        //第一个区间有数据
        be.next = as;
        if(as != null) {
            //第2个区间有数据
            ae.next = null;
        }
        return bs;
    }

2、找出两个链表的公共结点

 oj:160. 相交链表 - 力扣(LeetCode)

思路:

1. 分别求两个链表的长度

2. 让长的 head 先走差值步

3. head1 和 head2 同时走

4. 相遇的阶段就是要找的结点

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        ListNode pl = headA;
        ListNode ps = headB;

        int len1 = 0;
        int len2 = 0;

        //1、求长度
        while(pl != null) {
            len1++;
            pl = pl.next;
        }
        while(ps != null) {
            len2++;
            ps = ps.next;
        }
        pl = headA;
        ps = headB;
        int len = len1 - len2;
        if(len < 0) {
            //修正一下 pl和ps的指向
            pl = headB;
            ps = headA;
            len = len2-len1;
        }

        // 此时pl一定指向最长的链表,ps一定指向最短的链表;len一定是一个正数

        //2、走差值步
        while(len != 0) {
            pl = pl.next;
            len--;
        }
        //3、同时走
        while(pl != ps) {
            pl = pl.next;
            ps = ps.next;
        }
        // 两个链表没有交点
        if(ps == null) {
            return null;
        }
        // 4、返回相遇结点
        return pl;
    }

3、判断链表是否有环

oj:141. 环形链表 - 力扣(LeetCode)

思路:

1. 追击问题,在有环的情况下,使用快慢指针,fast 只要每次比 slow 多走一步,最终一定会相遇;fast 走2步,slow 走1步是最快的情况,因为它们最多追击一个环的长度,一定不会出现slow在环里走很多圈的情况。

2. 如果没有环,走得快的一定先为空,即 fast == null || fast.next == null

    public boolean hasCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                return true;
            }
        }
        return false;
    }

    public boolean hasCycle2(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                break;
            }
        }
        if(fast == null || fast.next == null) {
            return false;
        }
        return true;
    }

4、找到有环链表的入口点

oj:142. 环形链表 II - 力扣(LeetCode)

推导:

设起始点到入口点的距离为X,相遇点到入口点的距离为Y,环的长度为C

快指针走的路程:X+NC+(C-Y)

慢指针走的路程:X+(C-Y)

  2*(X+(C-Y))=X+NC+(C-Y)
  X+C-Y=NC
  X=NC-C+Y
  X=(N-1)*C+Y
  N=1时,X=Y

结论:无论 Y 在环中转了多少圈,让 slow 从头走,fast 从相遇点走,一步一步走,相遇的地方就是入口点

    public boolean detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                break;
            }
        }
        if(fast == null || fast.next == null) {
            return null;
        }
        slow = head;
        while(slow != fast){
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }

相关文章:

  • 前端实现OSS上传图片(Vue3+vant)
  • Linux---共享内存
  • FastAdmin 与其他后台框架的对比分析
  • Qt常用控件之旋钮QDial
  • 《从0到1:用Python在鸿蒙系统开发安防图像分类AI功能》
  • python流水线自动化项目教程
  • 设计一个“车速计算”SWC,通过Sender-Receiver端口输出车速信号。
  • java数据结构_Map和Set_9.1
  • “深入浅出”系列之音视频开发:(12)使用FFmpeg实现倍速播放:技术细节与优化思路
  • Spring Web MVC
  • leetcode---LCR 140.训练计划
  • 解决“两数之和”问题:两种实现方法详解
  • 02内存映射与bmp解码
  • DNS域名解析原理及解析过程
  • 【Java企业生态系统的演进】从单体J2EE到云原生微服务
  • 间隙波导阵列天线 学习笔记2 使用加载脊U型辐射层的一种Ka波段高效率圆极化卫星天线的发展
  • 【vscode-解决方案】vscode 无法登录远程服务器的两种解决办法
  • Week2 Using the Java Collection Libraries Lecture 2
  • 485 多路信号采集,校验干扰问题
  • 【齿轮——优化(预处理,去重,哈希)】
  • 吕梁做网站的公司/如何做电商赚钱
  • wordpress linux 重装/企业网站排名优化公司
  • 上海品划做网站/如何拿高权重网站外链进行互换?
  • 哈尔滨最新通知/seo软件系统
  • 服装网站建设方案摘要/三门峡网站seo
  • 阿里云自助建站教程/网站买卖交易平台