算法小知识-----04.16-----回文链表

116 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情

周六的痛苦面具加班日...

回文链表

该题出自力扣的234题 —— 回文链表【简单题】,虽然是道简单题,但是如果考虑复杂度的话就不简单了

审题

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

  • 该题的题意也很简单,主要就集中在回文链表里面 —— 也就是对称链表。[1,2,4,5,4,2,1]从头遍历和从尾遍历都一样的就属于对称链表
  • 解法很多:
    • 解法一: List 集合 + 双指针
      • 利用一个List 集合去装载整个链表的节点
      • 遍历链表,依次加入集合
      • 利用双指针去校验是否为回文链表(头尾指针分别开始,如果值不相等,则直接返回false)
      • 时间复杂度为O(n),因为需要遍历链表
      • 空间复杂度为O(n),因为需要开辟一个集合去装载
    • 解法二: 快慢指针 + 链表反转 + 对撞指针
      • 利用快慢指针,使慢指针走到链表的一半
      • 在慢指针的同时,利用反转链表,使得慢指针的前半部分链表反转
      • 最后获得一个链表的结构 —— 指针的前半部分是反转的,与后半部分行成反链
      • 利用对撞指针如解法一 一样校验是否为回文链表
      • 之所以使用快慢指针定位对称中间值,是因为如果要直接反转整条练的话,因为引用的是地址,所以需要额外开辟一条链去存储
      • 时间复杂度还是O(n)
      • 空间复杂度为O(1),优化了空间复杂度

编码

  • 双指针 + List集合
List<Integer> list = new ArrayList<>();
    public boolean isPalindrome(ListNode head) {
        while(head != null){
            list.add(head.val);
            head = head.next;
        }
        for (int i = 0,j = list.size()-1;i<=j;i++){
            if (!list.get(i).equals(list.get(j)))return false;
            j--;
        }
        return true;
    }
  • 双指针 + 快慢指针 + 链表反转
    public boolean isPalindrome(ListNode head) {
        ListNode pre = null,fast = head,slow = head;
        while (fast != null && fast.next != null){
            ListNode next = slow.next;
            if (pre != null){
                slow.next = pre;
            }
            pre = slow;
            fast = fast.next.next;
            slow = next;
        }
        if (fast != null)slow = slow.next;
        while (slow != null){
            if (slow.val != pre.val)return false;
            slow = slow.next;
            pre = pre.next;
        }
        return true;
    }