[Leetcode]234. Palindrome Linked List

Given a singly linked list, determine if it is a palindrome.

Example 1:

Input: 1->2
Output: false

Example 2:

Input: 1->2->2->1
Output: true

Follow up:
Could you do it in O(n) time and O(1) space?

 

这一题,主要价值就在于follow up上。如果没有O(1) space的限制的话做法太多,譬如自下而上的递归,或者更加直观可以用stack。这两者的本质是一样的,只是自下而上的递归写起来还是有点意思,可以认为是自下而上的一种基础练习。具体就不解释了,非常直白。直接给代码吧。

    public boolean isPalindrome(ListNode head) {
        if (head == null) return true;
        
        return recurCheck(new ListNode[]{head}, head);
    }
    
    public boolean recurCheck(ListNode[] head, ListNode cur) {
        if (cur.next == null) {
            boolean res = head[0].val == cur.val;
            head[0] = head[0].next;
            return res;
        } else {
            boolean res = recurCheck(head, cur.next);
            if (res) {
                res &= head[0].val == cur.val;
                head[0] = head[0].next;
            }
            return res; 
        }
    }

当然还有一种做法也很简单,reverse 这个list并且在reverse的过程里创造一个新的list,然后比较两个list是不是一样,具体就不写了。提供一下思路罢了

关于follow up,其实我觉得这可以归档到medium了。思维很定式也很取巧。利用到了两题的做法,Reverse Linked List和Linked List Cycle里快慢指针的思想。作为Palindrome的东西,可以认为是头尾往中间扫是一样的,但换一种想法,就是一个palindrome的东西,你反转它的后半部分(如果节点数为奇数可以忽略中间那个节点),那么它们前后两半是一样的。

这个follow up的解决思路就在此,
1. 利用快慢指针找到后半部分的起点。譬如1 -> 2 -> 2 -> 1里,如果你有快慢指针两个,一个一次走一步,一个一次走两步,那么当快指针走到终点的时候,慢指针刚好能走到第三个节点2那里。
2. 然后反转后半部分list,使之成为1->2->1->2。后半部分可以和前半部分分离,没所谓。
3. 你反转的过程里可以得到反转后的后半部分的head节点。也就是你这个时候有一个指针指向第一个节点1,另一个指针指向第三个节点1。
4. 同时前进,直到第二个指针走到尽头,如果一路匹配,则ok,否则吃屎。

根据以上思路,给出代码如下:

    public boolean isPalindrome(ListNode head) {
        if (head == null) return true;

        ListNode slow = head, fast = head, prev = null;
        while (fast != null) {
            prev = slow;
            slow = slow.next;
            fast = fast.next == null ? fast.next : fast.next.next;
        }
        prev.next = reverseList(slow);
        slow = head;
        fast = prev.next;
        
        while (fast != null) {
            if (slow.val != fast.val) return false;
            slow = slow.next;
            fast = fast.next;
        }
        
        return true;
    }
    
    public ListNode reverseList(ListNode head) {
        ListNode prev = null, cur = head;
        while (cur != null) {
            ListNode next = cur.next;
            cur.next = prev;
            prev = cur;
            cur = next;
        }
        
        return prev;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值