0
点赞
收藏
分享

微信扫一扫

《新星计划之链表》环形链表、回文链表(图解分析)

Ewall_熊猫 2022-05-06 阅读 49

目录

环形链表

 回文链表


 

环形链表

这样的话如果链表中存在环的话,他们两个一定会相遇,如图所示:
 

 

代码如下:

// 环形链表
public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head, show = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            show = show.next;
            if (fast == show) {
                return true;   // 如果有环的话,他们两个一定能相遇
            }
        }
        return false;
    }
}

但这里有一个小细节,在while的循环条件里fast != null这个判断条件不能丢

为啥呢?如图所示:


 

 回文链表

🍑所以我们不妨换个思路,你看如果一个链表是回文链表的话:它是不是正好分成了两个部分,既然我们不能反转整个链表,那么我们能不能对链表的后半部分进行反转,这样如果反转后的后半部分和前半部分是重合的,那么就说明这是一个回文链表。

 

🍑那么问题又来了?我们怎样把链表分为两部分呢?就是如上图所示只有我们能够找到链表的中间位置3就好。

我们定义两个结点的引用fast和slow,fast每次移动两个结点,slow每次移动一个结点。

能够移动的条件就是:

开始时

 结束时

📝总结一下就是:

  1. 用快慢指针找到中间位置,把代码分为前后两个部分
  2. 对后半部分进行旋转操作
  3. 比较前后两个部分是否相等
class Solution {
    // 首先要找到中间结点
    public ListNode midFind(ListNode slow, ListNode fast) {
       
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;  // 此时慢指针所指向的就是中间结点
    }
    // 反转链表,把中间结点之后的结点进行反转
    public ListNode reverseList(ListNode cur) {
        ListNode pre = null;
        while(cur != null) {
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
   }
    // 判断前后两部分是否相等
    public boolean isPalindrome(ListNode head) {
        ListNode dummyHead = new ListNode(0, head);  // 设置虚拟头结点,当结点只有较少时方便处理
        ListNode mid = midFind(dummyHead, dummyHead); // mid链表的中间结点
        // 对中间结点往后的后半部分进行反转
        ListNode tail = reverseList(mid.next);
        while(dummyHead != mid && head != null && tail != null) {
            if (head.val != tail.val) {
                return false;
            }
            head = head.next; 
            tail = tail.next;
        }
        return true;
    }

}
举报

相关推荐

0 条评论