题目

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

样例

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

lintcode 中等题:Palindrome Linked List 回文链表的更多相关文章

  1. [CareerCup] 2.7 Palindrome Linked List 回文链表

    2.7 Implement a function to check if a linked list is a palindrome. LeetCode上的原题,参见我之前的博客Palindrome ...

  2. [LeetCode] Palindrome Linked List 回文链表

    Given a singly linked list, determine if it is a palindrome. Follow up: Could you do it in O(n) time ...

  3. [LeetCode] 234. Palindrome Linked List 回文链表

    Given a singly linked list, determine if it is a palindrome. Example 1: Input: 1->2 Output: false ...

  4. 234 Palindrome Linked List 回文链表

    请检查一个链表是否为回文链表. 进阶:你能在 O(n) 的时间和 O(1) 的额外空间中做到吗? 详见:https://leetcode.com/problems/palindrome-linked- ...

  5. [Swift]LeetCode234. 回文链表 | Palindrome Linked List

    Given a singly linked list, determine if it is a palindrome. Example 1: Input: 1->2 Output: false ...

  6. LeetCode 234:回文链表 Palindrome Linked List

    ​ 请判断一个链表是否为回文链表. Given a singly linked list, determine if it is a palindrome. 示例 1: 输入: 1->2 输出: ...

  7. LeetCode OJ:Palindrome Linked List(回文链表判断)

    Given a singly linked list, determine if it is a palindrome. Follow up:Could you do it in O(n) time ...

  8. 如何判断一个单向链表是否为回文链表(Palindrome Linked List)

    题目:给定一个单向链表,判断它是不是回文链表(即从前往后读和从后往前读是一样的).原题见下图,还要求了O(n)的时间复杂度O(1)的空间复杂度. 我的思考: 1,一看到这个题目,大脑马上想到的解决方案 ...

  9. 回文链表 · Palindrome Linked List

    [抄题]: 设计一种方式检查一个链表是否为回文链表.1->2->1 就是一个回文链表. [暴力解法]: 时间分析: 空间分析: [思维问题]: 以为要从从后往前扫描,不知道调用revers ...

随机推荐

  1. DWZ前端框架使用问题记录

    心得体验:DWZ依赖特定的HTML结构,所以一定要注意项目中的HTML结构,多用firebug查看,还有如果使用一些组件的时候出现问题,可以查看下返回JSON格式是否符合组件规定的JSON格式,很多都 ...

  2. 将json转为复杂url参数

    //json转url参数 var parseParam = function(param, key) { var paramStr = ""; if (param instance ...

  3. SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪

    来源:http://www.cnblogs.com/downmoon/archive/2012/04/10/2439462.html  本文主要介绍SQL Server中记录数据变更的四个方法:触发器 ...

  4. JAVA中toString方法

    因为它是Object里面已经有了的方法,而所有类都是继承Object,所以"所有对象都有这个方法". 它通常只是为了方便输出,比如System.out.println(xx),括号 ...

  5. Eclipse C/C++开发环境搭建

    1 Eclipse的安装 到http://java.sun.com/j2se/1.5.0/download.jsp 下载JRE安装: 到http://eclipse.org下载Eclipse安装.(这 ...

  6. final ,override关键字

    final 有时我们会定义这样一种类,我们不希望其他类继承它,或者不想考虑它是否适合作为一个基类.为了实现这一目的,c++ 11新标准提供了一种防止继承发生的方法,即在类名后跟一个关键字final: ...

  7. VB 思维导图总结(三)

    续上篇.vb总结之“思维导图”(2) 第十章.绘制图形 第十一章.数据库技术... 第十二章.总结! 相信有了vb的一个基础,应对接下来的学习会顺畅些.加油!

  8. .net speed up

    Ngen.exe http://www.cnblogs.com/yukaizhao/archive/2011/11/07/how-to-use-ugen.html Merge.exe Merge dl ...

  9. python学习小结4:类

    虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程. 类和对象是面向对象编程的两个主要方面.类:创建一个新类型,而对象是这个类的实例,类使用class关键字创建.类的域和方法被列在一个 ...

  10. SSH与EJB 比较

    SSH完全的开源产品,如果用SSH就必然会用到大量的开源的东东,从数据库到逻辑到控制到前端,开源产品大拼装, 其中SSH中的三大核心,Struts相当于JSF,spring相当于EJB,hiberna ...