您的位置:首页 > 编程语言 > Java开发

LeetCode234_PalindromeLinkedList (判断是否为回文链表) Java题解

2015-07-29 11:40 555 查看
题目:

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

Follow up:

Could you do it in O(n) time and O(1) space?
题解:
判断一个链表是不是回文的,这里要求O(n)时间复杂度和O(1)的空间时间复杂度,总共想了三种办法,三种办法都用到了两个指针,符合题目要求的只有最后一种。

第一种办法:用数组倒着存前半段的链表的值,然后和后半段链表的值进行比较。这种解法运行的时间最久可能是因为数组倒着插入比较耗时。

代码:

//用数组实现 o(n/2)空间
public static boolean isPalindrome(ListNode head) {

// ArrayList<Integer> nodeVal=new ArrayList<>();
LinkedList<Integer> nodeVal=new LinkedList<>();

if(head==null||head.next==null)
return true;
ListNode slow=head;
ListNode fast=head;

nodeVal.add(0,slow.val);
while(fast.next!=null&&fast.next.next!=null)
{
fast=fast.next.next;
slow=slow.next;
nodeVal.add(0,slow.val);
}

ListNode cur=slow;
if(fast.next!=null)//链表长度为偶数
cur=slow.next;
int i=0;
while(cur!=null)
{
if(nodeVal.get(i)!=cur.val)
return false;
cur=cur.next;
i++;
}
return true;
}
第二种解法:在第一种的思路的基础上,我们要实现一个倒序,我们干嘛不用现成的数据结构-栈,于是把链表前半段压栈,然后出栈和后面的链表依次比较,这种运行时间最短,但因为用到了栈还是不符合题目要求。

代码:

//用栈实现
public static boolean isPalindrome2(ListNode head) {

Stack<ListNode> stack=new Stack<>();
ListNode slow=head;
ListNode fast=head;

if(fast==null||fast.next==null)//0个节点或是1个节点
return true;

stack.push(slow);
while(fast.next!=null&&fast.next.next!=null)
{

fast=fast.next.next;
slow=slow.next;
stack.push(slow);
}
if(fast.next!=null)//链表长度为偶数
slow=slow.next;

ListNode cur=slow;
while(cur!=null)
{
if(cur.val!=stack.pop().val)
return false;
cur=cur.next;
}
return true;

}


第三种:我们这样想,我们可不可以不借助外在的存储实现倒序呢,其实是可以的,链表反转的时候我们就没有借助外在存储。思路是把后半段的原地链表反转然后和前半段进行比较(当然你也可以反转前半段)运行时间稍微比第二种慢一些,但是符合题目O(1)空间复杂度的要求

代码:

//链表原地转置实现o(1)空间复杂度
public static boolean isPalindrome3(ListNode head) {
ListNode slow=head;
ListNode fast=head;

if(fast==null||fast.next==null)//0个节点或是1个节点
return true;

while(fast.next!=null&&fast.next.next!=null)
{
fast=fast.next.next;
slow=slow.next;
}
//对链表后半段进行反转
ListNode midNode=slow;
ListNode firNode=slow.next;//后半段链表的第一个节点
ListNode cur=firNode.next;//插入节点从第一个节点后面一个开始
firNode.next=null;//第一个节点最后会变最后一个节点
while(cur!=null)
{
ListNode nextNode=cur.next;//保存下次遍历的节点
cur.next=midNode.next;
midNode.next=cur;
cur=nextNode;
}

//反转之后对前后半段进行比较
slow=head;
fast=midNode.next;
while(fast!=null)
{
if(fast.val!=slow.val)
return false;
slow=slow.next;
fast=fast.next;
}
return true;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: