现给定一个链表ListNode* pHead,定义bool代表链表是否为回文,请编写程序。
测试样例:
{1,2,3,2,1} 返回:true
{1,2,3,2,3} 返回:false
public class Palindrome {
public boolean isPalindrome(ListNode pHead){
ListNode fast = pHead;
ListNode slow = pHead;
Stack<Integer> stack = new Stack<Integer>();
/**
* 将链表的前半部分元素装入栈中,当快速runner
*(移动的速度是慢速runner的两倍)
* 到底链表尾部时,则慢速runner已经处于链表中间位置
*/
while(fast != null && fast.next != null){
stack.push(slow.val);
slow = slow.next;
fast = fast.next.next;
}
//当链表为奇数个时,跳过中间元素
if (fast != null) {
slow = slow.next;
}
while(slow != null){
//如果两者不相同,则该链表不是回文串
if (stack.pop() != slow.val) {
return false;
}
slow = slow.next;
}
return true;
}
}
题目分析:
《方法1》:反转链表
可以将原始链表反转,判断反转以后的链表与原始链表是否完全一致,如果一致便返回true,如果不一致则返回false。反转链表需要额外的存储空间,不是特别优秀的方法。
《方法2》:栈实现
我们可以想到从中间节点向两侧开始比较,如果全部相同,则返回true,否则返回false,因为无法获得一个节点的前一个节点,这个时候我们可以想到用栈实现,先将链表前半部分的元素分别压入堆栈,然后在遍历后半部分元素的时候同时和栈顶元素进行比较,如果全部相等则返回true,否则返回false。
特别注意:因为我们不知道链表的的长度,可以通过快慢指针(一个指针每次移动两个,一个指针每次移动一个)来找到中间元素,这样整体只需要遍历链表一次,所需要的栈空间缩小为方法1的一半。
《方法3》:递归法
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
// write code here
ListNode *tail=pHead;
int length=0;
while(tail)
{
++length;
tail=tail->next;
}
return isPalindrome1(pHead,&tail,length);
}
bool isPalindrome1(ListNode* pHead,ListNode **tail,int length)
{
if(pHead==NULL||length==0)
return true;
if(length==1)
{
*tail=pHead->next;
return true;
}
if(length==2)
{
*tail=pHead->next->next;
return pHead->val==pHead->next->val;
}
bool sign=isPalindrome1(pHead->next,tail,length-2);
if(sign==false)
return false;
ListNode* tail1=*tail;
*tail=tail1->next;
return pHead->val==tail1->val;
}
};
采用递归的方式,将p定义成static:
每次传入一个新的链表,让p指向链表首节点。
通过递归,pHead从后往前,p从前往后,同时比较。
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
// write code here
if(pHead==NULL)
return true;
static ListNode* p=NULL;
if(p==NULL) p=pHead;
if(isPalindrome(pHead->next)&&(p->val==pHead->val))
{
p=p->next;
return true;
}
p=NULL;
return false;
}
};
/*用数组方式进行添加的,不过数组扩容速度慢(数组最快3n),其他用户的快慢指针是一种办法,
虽然复杂度O(n),但是快慢指针更快(2n)*/
public class Palindrome {
public boolean isPalindrome(ListNode pHead) {
// write code here
ArrayList<Integer> list = new ArrayList<Integer>();
if(pHead == null){
return false;
}
ListNode node = pHead;
while(node != null){
list.add(node.val);
node = node.next;
}
int N = list.size();
for(int i = 0;i < N/2; i++){
if(list.get(i) != list.get(N-i-1)){
return false;
}
}
return true;
}
}
//将链表的后半部分翻转,然后从开头和中间处分别遍历
bool isPalindrome(ListNode* pHead) {
if(pHead == NULL || pHead->next == NULL) return true;
//翻转后半部分链表
ListNode* fast = pHead, *slow = pHead;
while(fast->next != NULL){
fast = fast->next;
if(fast->next != NULL){
fast = fast->next;
slow = slow->next;
}
}
while(slow->next != fast){
ListNode* tmp = slow->next;
slow->next = tmp->next;
tmp->next = fast->next;
fast->next = tmp;
}
//分别从中间和后半部分开始遍历
while(fast != NULL){
if(fast->val != pHead->val)
return false;
fast = fast->next;
pHead = pHead->next;
}
return true;
} import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Palindrome {
public boolean isPalindrome(ListNode pHead) {
// write code here
Stack<Integer> stack = new Stack<Integer>();
Queue<Integer> queue = new LinkedList<Integer>();
int flag = 0;
while(pHead != null){
stack.push(pHead.val);
queue.add(pHead.val);
pHead = pHead.next;
}
while(!stack.isEmpty()){
if(stack.peek() != queue.peek()){
return false;
}
stack.pop();
queue.poll();
}
return true;
}
}
使用栈和队列实现功能
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Palindrome {
public boolean isPalindrome(ListNode pHead) {
// write code here
String str = "";
String str2 = "";
while(pHead!=null){
str = str+String.valueOf(pHead.val);
str2 = String.valueOf(pHead.val)+str2;
pHead = pHead.next;
}
if(str.equals(str2)){
return true;
}else{
return false;
}
}
}
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
vector<int> seq;
while (pHead) {
seq.push_back(pHead->val);
pHead = pHead->next;
}
for (int i=0; i<seq.size() / 2; ++i) {
int j = seq.size() - i - 1;
if (seq.at(i) != seq.at(j)) { return false; }
}
return true;
}
};
运行时间:4ms
占用内存:612k
不使用额外空间,反转后半部分链表,然后一个指针指向链表头,一个指针指向链表中间,
比较值是否相等,不相等就返回false。
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
// write code here
int count=0;
ListNode* p=pHead;
while(p!=NULL){
p=p->next;
count++;
}
count=count%2==0?count/2:(count/2+1);
p=pHead;
for(int i=0;i<count;++i){
p=p->next;
}
ListNode* pre=NULL;
while(p!=NULL){
ListNode* temp=p->next;
p->next=pre;
pre=p;
p=temp;
}
ListNode* m=pHead;
while(pre!=NULL&&m!=NULL){
if(pre->val!=m->val)
return false;
pre=pre->next;
m=m->next;
}
return true;
}
};
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Palindrome {
public boolean isPalindrome(ListNode pHead) {
// write code here
// 快慢指针找到链表中间位置节点
// 将链表前半部入栈,然后在遍历后半部分时,将元素逐一弹出,进行比较
// 注意处理链表的奇偶,如果为奇,跳过中间节点
ListNode fast = pHead;
ListNode slow = pHead;
Stack<Integer> stack = new Stack<Integer>();
while(fast != null && fast.next != null){
stack.push(slow.val);
slow = slow.next;
fast = fast.next.next;
}
if (fast != null) {
slow = slow.next;
}
while(slow != null){
if (stack.pop() != slow.val) {
return false;
}
slow = slow.next;
}
return true;
}
}
import java.util.*;
//两点关键:快慢指针可以找到中间点,如果快指针不为空,则为奇数个,慢指针此时指向中间点,否则无中间点
//单向链表指针不能往回走,所以通过将前半节打入栈中的方式完成(栈的特性 后进先出)
public class Palindrome {
public boolean isPalindrome(ListNode pHead) {
ListNode slow =pHead;
ListNode fast =pHead;
Stack<Integer> stack =new Stack<Integer>();
while(fast!=null&&fast.next!=null ){//找到中间点,并将前半节打入栈中
stack.push(slow.val);
slow =slow.next;
fast =fast.next.next;
}
if(fast!=null){
slow =slow.next;
}
while(slow.next!=null){//指针从中间点开始每下移一个,就与栈中取出的值对比
if(slow.val !=stack.pop()){
return false;
}
slow =slow.next;
}
return true;
}
}
bool isPalindrome(ListNode* pHead) {
// write code here
if (pHead == nullptr)
return false;
ListNode * p = pHead;
ListNode * q ;
ListNode * reverse = new ListNode(0);
reverse->next = nullptr;
while (p != nullptr){
q = new ListNode(p->val);
q->next = reverse->next;
reverse->next = q;
p = p->next;
}
p = pHead;
q = reverse->next;
while (p != nullptr && q != nullptr){
if (p->val != q->val)
return false;
p = p->next;
q = q->next;
}
return true;
}
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Palindrome:
def isPalindrome(self, pHead):
if not pHead or not pHead.next:
return False
stack = []
slow = pHead
fast = pHead.next
stack.append(slow.val)
while True:
# 链表是偶数长度
if not fast.next:
mid = slow.next
break
elif fast.next and not fast.next.next:
mid = slow.next.next
break
slow = slow.next
fast = fast.next.next
stack.append(slow.val)
while stack and mid:
top = stack.pop()
if top != mid.val:
return False
mid = mid.next
return True
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
// write code here
vector<int> a;
while(pHead)
{
a.push_back(pHead->val);
pHead=pHead->next;
}
for(int i=0;i<a.size()/2+1;i++)
{
if(a[i]!=a[a.size()-1-i])
return false;
}
return true;
}
};
可以把链表的值传入数组,利用数组进行判断链表是否为回文链表
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
// write code here
if (pHead == NULL || pHead->next == NULL) return true;
ListNode* slow = pHead;
ListNode* fast = pHead;
while (fast->next && fast->next->next)
{
slow = slow->next;
fast = fast->next->next;
}
fast = slow->next;
stack<int> stk;
while (fast)
{
stk.push(fast->val);
fast = fast->next;
}
slow = pHead;
while (!stk.empty())
{
if (stk.top() != slow->val) return false;
stk.pop();
slow = slow->next;
}
return true;
}
}; //不需要那么复杂,直接转换为字符串,直接判断就可以了
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
if(pHead==nullptr||pHead->next==nullptr)
return true;
string str="";
while(pHead!=nullptr)
{
str+=to_string(pHead->val);
pHead=pHead->next;
}
return str==string(str.rbegin(),str.rend());
}
};
快慢指针+反转慢链一把梭.
用了快慢指针就强迫症不想用栈.
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
if(!pHead) return true;
ListNode* slow = pHead;
ListNode* fast = slow;
ListNode *tmp = nullptr;
ListNode *last = nullptr;
while (slow && fast && fast->next) {
fast = fast->next->next;
tmp = slow;
slow = slow->next;
tmp->next = last;
last = tmp;
}
if (fast) slow = slow->next;
while(slow && last) {
if(slow->val != last->val) return false;
slow = slow->next;
last = last->next;
}
return true;
}
};
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
// write code here
if(pHead==NULL)return true;
while(pHead!=NULL){
ListNode*pTail=pHead;
if((pTail->next)==NULL)return true;
while((pTail->next->next)!=NULL)pTail=pTail->next;
if((pTail->next->val)!=(pHead->val))return false;
pTail->next=NULL;
pHead=pHead->next;
}
return true;
}
};