现给定一个链表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; } };