• lintcode 中等题:Palindrome Linked List 回文链表


    题目

    设计一种方式检查一个链表是否为回文链表。

    样例

    1->2->1 就是一个回文链表。

    挑战

    O(n)的时间和O(1)的额外空间。

    解题

    法一:

    再定义一个链表,存放链表反转的值,再以此比较两个链表中的值是否相等,时间复杂度O(N),空间复杂度O(N)

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        /**
         * @param head a ListNode
         * @return a boolean
         */
        public boolean isPalindrome(ListNode head) {
            // Write your code here
            ArrayList<Integer> list = new ArrayList<Integer>();
            if(head == null || head.next == null)
                return true;
            ListNode p = head;
            ListNode prev = new ListNode(head.val);
            while(p.next != null){
                ListNode tmp = new ListNode(p.next.val);
                tmp.next = prev;
                prev = tmp;
                p = p.next;
            }
            ListNode p1 = head;
            ListNode p2 = prev;
            while(p1!=null){
                if(p1.val != p2.val)
                    return false;
                p1 = p1.next;
                p2 = p2.next;
            }
            return true;
         
        }
    }
    Java Code

    总耗时: 2219 ms

    Python下面程序出现内存溢出

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return a boolean
        def isPalindrome(self, head):
            # Write your code here
            if head == None or head.next == None:
                return True
            p = head
            prev = ListNode(head.val)
            while p.next!=None:
                tmp = ListNode(p.next.val)
                tmp.next = prev
                prev = tmp
                p = p.next
            p1 = head
            p2 = prev
            del head
            del prev
            while p1!=None:
                if p1.val != p2.val:
                    return False
                p1 = p1.next
                p2 = p2.next
            return True 
    Python Code

    法二:

    先找到链表的中间节点,根据中间节点划分成两个链表,对第二个链表反转后在和第一个链表元素以此比较,但是下面的程序,在旋转的过程中空间复杂度好像是O(N/2) = O(N)

    在找中间节点时候需要说明下

            ListNode slow = head;
            ListNode fast = head;
            // 找到两个链表的中间节点
            while( fast.next!=null && fast.next.next!=null){
                fast = fast.next.next;
                slow = slow.next;
            }

    开始时候两个节点都指向第一个节点,以后两个异步的向前走

    最后结束的时候

    当长度是奇数的时候:slow恰好在中间节点,fast恰好在最后一个节点。slow.next就是下一个链表的头节点。你会发现这两个链表是不一样的长的,但是在比较的时候,只要有一个链表是null的时候就结束比较的,也就是说只与第二个链表有关系的。

    当长度是偶数的时候:slow在N/2的下取整处的节点,也就是中间两个节点的前一个,二fast在倒数第二个节点,下面就一样了

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        /**
         * @param head a ListNode
         * @return a boolean
         */
        public boolean isPalindrome(ListNode head) {
            // Write your code here
            if(head == null || head.next == null)
                return true;
            ListNode slow = head;
            ListNode fast = head;
            // 找到两个链表的中间节点
            while( fast.next!=null && fast.next.next!=null){
                fast = fast.next.next;
                slow = slow.next;
            }
            ListNode secondHead = slow.next;
            slow.next = null;
            // 后半部分的节点反转
            ListNode p1 = secondHead;
            ListNode revsecondList = new ListNode(p1.val);
            revsecondList.next = null;
            while(p1.next != null){
                ListNode tmp = new ListNode(p1.next.val);
                tmp.next = revsecondList;
                revsecondList = tmp;
                p1 = p1.next;
            }
            
            // 比较两个链表
            while(head!=null && revsecondList!=null){
                if(head.val != revsecondList.val)
                    return false;
                head = head.next;
                revsecondList = revsecondList.next;
            }
            return true;
        }
    }
    Java Code

    总耗时: 2229 ms

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return a boolean
        def isPalindrome(self, head):
            # Write your code here
            if head == None or head.next == None:
                return True
            slow = head
            fast = head
            while fast.next != None and fast.next.next != None:
                fast = fast.next.next
                slow = slow.next
            secondHead = slow.next
            slow.next = None
            p = secondHead
            rev = ListNode(p.val) 
            
            while p.next!=None:
                tmp = ListNode(p.next.val)
                tmp.next = rev
                rev = tmp
                p = p.next
    
            while rev!=None and head!=None:
                if rev.val != head.val:
                    return False
                rev = rev.next
                head = head.next
            return True 
    Python Code

    总耗时: 528 ms

    在旋转链表的时候有重新定义了节点,如何只是修改节点而实现翻转,下面利用递归的思想翻转链表,但是在测试到97%的数据的时候运行时间超时。

        public ListNode reverse(ListNode head){
            if(head == null || head.next == null)
                return head;
            ListNode second = head.next;
            head.next = null;
            ListNode res = reverse(second);
            second.next = head;
            return res;
        }
    Java Code

    下面是定义两个指针,第一个指向头节点,第二个指向头节点后一个节点

    p1 = head
    p2 = p1.next
    while(p1!= null && p2!= null){ ListNode tmp = p2.next; p2.next = p1; p1 = p2; p2 = tmp; }

    操作如下图所示

    这里可以最后A还指向B的,可以在初始定义中增加

    p1 .next = null

    这样每次都是在p1节点之前增加一个节点的

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        /**
         * @param head a ListNode
         * @return a boolean
         */
        public boolean isPalindrome(ListNode head) {
            // Write your code here
            if(head == null || head.next == null)
                return true;
            ListNode slow = head;
            ListNode fast = head;
            // 找到两个链表的中间节点
            while( fast.next!=null && fast.next.next!=null){
                fast = fast.next.next;
                slow = slow.next;
            }
            ListNode secondHead = slow.next;
            slow.next = null;
            // 后半部分的节点反转
            ListNode p1 = secondHead;
            ListNode p2 = p1.next;
            p1.next = null;
    
            while(p1!= null && p2!= null){
                ListNode tmp = p2.next;
                p2.next = p1;
                p1 = p2;
                p2 = tmp;
            }
            secondHead.next = null;
            revsecondList = p1;
            // 比较两个链表
            while(head!=null && revsecondList!=null){
                if(head.val != revsecondList.val)
                    return false;
                head = head.next;
                revsecondList = revsecondList.next;
            }
            return true;
        }
    }
    Java Code

    总耗时: 2192 ms

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return a boolean
        def isPalindrome(self, head):
            # Write your code here
            if head == None or head.next == None:
                return True
            fast = head
            slow = head
            while fast.next!= None and fast.next.next!=None:
                fast =fast.next.next
                slow = slow.next
            secondhead = slow.next
            slow.next = None
            
            p1 = secondhead
            p2 = p1.next
            p1.next = None
            while p1!=None and p2!=None:
                tmp = p2.next
                p2.next = p1
                p1 = p2
                p2 = tmp
            rev = p1
            while rev!=None and head!=None:
                if rev.val!=head.val:
                    return False
                rev = rev.next
                head = head.next
            return True 
    Python Code

    总耗时: 516 ms

  • 相关阅读:
    SQL update select
    Centos7 update dotnet 无法识别
    asp.net core mvc 在中间件中使用依赖注入问题:System.InvalidOperationException: Cannot resolve scoped service 'IXXXService' from root provider.
    SQL Server类型与C#类型对应关系
    .NET Core ABP
    支付宝小程序获取用户授权
    .Net 多线程,异步且控制并发数量
    SQL:尝试将不可为 NULL 的列的值设置为 NULL
    .Net Core依赖注入和服务注册
    .NET Core配置主机端口的几种方式
  • 原文地址:https://www.cnblogs.com/theskulls/p/4940695.html
Copyright © 2020-2023  润新知