本次写的题目是链表的回文结构,为牛客网里面的题目,让我们来康康是如何解出这道题目的吧,各位尚没有思路的小伙伴可以跟随着博主的解题思路一步步来,感受一下😎
🌱分析阶段
博主在看到本题的第一个想法是可不可以找出中间位置之后一一对比,如下图👇:
在思考了之后其实可行性不高,那么就开始思考有没有什么技巧可以用到,或者之前写过的什么题目里面的方法可以用到这里,来变换一下链表。
在思考过后,认为可以用到博主之前写过的翻转链表题目与快慢结点技巧😎
具体操作分为三步:
- 找到中间结点
- 将后半部分链表翻转
- 对比是否相等
如果有写过中间结点与翻转链表的基础的话,这题是十分容易解决的,若没有这方面基础,这里博主推荐先写LeetCode中的这两道题:翻转链表、返回链表的中间结点。也可以直接看博主写的这两道题的解答😎LeetCode第206题—反转链表与LeetCode第876题—链表的中间结点
掌握了这两个技巧之后,我们就直接进入到代码部分吧😎
🌱代码阶段
代码阶段基本上与翻转链表与返回链表的中间结点的代码部分无异,于是先写出下面部分👇:
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {
if(A==null) return false;
if(A.next==null) return false;
ListNode slow = A.next;
ListNode fast = A.next.next;
while(fast!=null&&fast.next!=null){ //当退出的时候cur就为中间结点
fast = fast.next.next;
slow = slow.next;
}
//拿到中间结点之后,就是翻转链表
ListNode cur = slow.next;
ListNode nextNode = slow.next.next;
while(nextNode!=null){
cur.next = slow;
slow = cur;
cur = nextNode;
nextNode = nextNode.next;
}
cur.next = slow;
slow = cur;
}
}
唯一需要注意的是剩下的对比阶段,我们先以单数链表为例,写出下面的代码:
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {
if(A==null) return false;
if(A.next==null) return false;
ListNode slow = A.next;
ListNode fast = A.next.next;
while(fast!=null&&fast.next!=null){ //当退出的时候cur就为中间结点
fast = fast.next.next;
slow = slow.next;
}
//拿到中间结点之后,就是翻转链表
ListNode cur = slow.next;
ListNode nextNode = slow.next.next;
while(nextNode!=null){
cur.next = slow;
slow = cur;
cur = nextNode;
nextNode = nextNode.next;
}
cur.next = slow;
slow = cur;
//翻转完后就需要比对,此时的的slow是用来比对的,翻转后可以让slow一直往下走,对比
ListNode newHead = A;
while(A!=slow){
if(A.val!=slow.val){
return false;
}
A = A.next;
slow = slow.next;
}
return true;
}
}
这里忽略了双数链表的对比情况,如果按照目前代码运行,若碰到双数链表,该代码会进入死循环,所以我们需要在最后的while语句内部再加双数链表的判断👇:
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {
if(A==null) return false;
if(A.next==null) return false;
ListNode slow = A.next;
ListNode fast = A.next.next;
while(fast!=null&&fast.next!=null){ //当退出的时候cur就为中间结点
fast = fast.next.next;
slow = slow.next;
}
//拿到中间结点之后,就是翻转链表
ListNode cur = slow.next;
ListNode nextNode = slow.next.next;
while(nextNode!=null){
cur.next = slow;
slow = cur;
cur = nextNode;
nextNode = nextNode.next;
}
cur.next = slow;
slow = cur;
//翻转完后就需要比对,此时的的slow是用来比对的,翻转后可以让slow一直往下走,对比
ListNode newHead = A;
while(A!=slow){
if(A.val!=slow.val){
return false;
}
if(A.next==slow){ //若A的下一个就是slow,相当于此时A与slow都是中间结点
return true;
}
A = A.next;
slow = slow.next;
}
return true;
}
}
至此,全部代码才算完成,让我们来运行来逝逝吧😎
nice😎✨
加一句题外话:这道题目其实还有另外一直解法,该解法需要用到栈相关知识,这里卖个关子,之后博主写到栈相关知识的时候再来揭晓,有已经学到栈相关知识的小伙伴也可以自己先逝逝😎加油