题目
设计一种方式检查一个链表是否为回文链表。
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; } }
总耗时: 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
法二:
先找到链表的中间节点,根据中间节点划分成两个链表,对第二个链表反转后在和第一个链表元素以此比较,但是下面的程序,在旋转的过程中空间复杂度好像是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; } }
总耗时: 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
总耗时: 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;
}
下面是定义两个指针,第一个指向头节点,第二个指向头节点后一个节点
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; } }
总耗时: 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
总耗时: 516 ms