判断链表相等的“低级问题”?

379 阅读3分钟

开胃:

有两个链表:L1和L2; L1: 1->2->3->4, L2: 1->2->3->5

  • 问:L1和L2 相等吗? (用“==”和"equals"做判断) 具体代码如下:
    private static boolean test1() {
        ListNode l1 = new ListNode(1);
        l1.next = new ListNode(2);
        l1.next.next = new ListNode(3);
        // 不一样的节点
        l1.next.next.next = new ListNode(4);

        ListNode l2 = new ListNode(1);
        l2.next = new ListNode(2);
        l2.next.next = new ListNode(3);
        // 不一样的节点
        l2.next.next.next = new ListNode(5);

        if (l1==l2) {
            return true;
        }
        return false;
    }

脱口而出的答案:

作为一个写java的程序员,你不用拍大腿就能给答案: 当然不相等 ,对,确实不相等,No matter what you use "==" or "equal" to operate it , it always return a “false” for you !

进入场景,再细品:

  • 让我们走进leetcode 环形链表2 里面有一行 slow == fast 是业务核心,这行代码要是没有的话,代码在运行时就会超出时间限制;

slow == fast 的源头:

撇看整体看局部,味同嚼蜡,我上题解代码 :感谢 博主 南京大乱炖

public ListNode detectCycle(ListNode head) {
        // 边界条件
        if (head == null) {
            return null;
        }
        // 快慢指针
        ListNode fast = head;
        ListNode slow = head;
        // 每次循环,快的比慢的多跑一步,在循环体里,就呈现出一种现象,fast指针,在追slow 指针
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            // 核心判断:重点看一下,这个"==" 操作,到底在链表什么条件下会返回true呢?
            if (slow == fast) {
                // 退出这个点,就是相遇点;
                break;
            }
        }

        if (fast == null || fast.next == null) {
            return null;
        }
        
        fast = head;
        while (slow != fast) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }

debug it :

  • 重点代码重点分析:
// 核心判断:重点看一下,这个"==" 操作,到底在链表什么条件下会返回true呢?
if (slow == fast) {
   // 退出这个点,就是相遇点;
   break;
 }

环装链表.png

  • 创建的结果(先撇开stackOverFlow 异常,主要检查是否有环?)

创建的环状链表.png

  • 记住哈,最最开始的时候,fast指针和slow 是相等的哦!

slow 和fast是相等的.png

注意: 当fast 的速度快与slow 时,他俩就不相等了;

  • fast 开始追赶slow ,直到 相等! 主要:我们想知道的相等,总算可以见到了;

相等时.png

  • 再看一眼 hash

fast.png

slow.png 这下子,是不是 恍然大悟? 不管你 链表 L1 和 L2 是创建的,还是从某一相同链表Head 截图的? 判断相等,本质是 用的HashCode;

错误的认识:

临时链表.jpg

  • 如上图所示,链表:L1 和 L2,当前节点 都是 1.此时 L1==L2 吗?
  • 一开始,我认为是相等的,因为节点都是1,"=="做比较的时候,是排除L1的 2,4 节点,排除L2 的2,5 节点; 可是刷着刷着,总感觉不对劲,我认为的排除,是不是违反了OOP中的 封装 思想呢? 节点2,是节点1 的next 属性,节点4 是节点2的属性,L2 节点;
  • 所以:l1==l2,并不是以current 节点(就是1节点来做是否相等判断的),而是以整个链表的hashcode 作为依据,来进行判断的;(全局观)那是真相等啊....

思考:

  • 刷题时,弄清楚每行代码的来龙去脉,真的太重要了,窥一斑而知全豹;
  • 刷题,真的有用;