判断回文链表
回文数的特点就是从左往右和从右往左是一样的顺序
判断是不是回文链表就利用这一特点
12321 这就是一组回文数
解决回文链表的思想
- 将原来的链表拷贝一份并且反转(这样做是为了不改变原有链表),如果原链表是回文链表则新拷贝的链表和原来的链表是一样的,此时只需要同时遍历两个链表然后逐个比较
代码如下:
// 拷贝链表并且反转
ListNode temp = head;
ListNode newNode = null;
ListNode newTemp = null;
while(temp!=null){
newNode = new ListNode(temp.val);
newNode.next = newTemp;
newTemp = newNode;
temp = temp.next;
}
// 同时遍历两个链表
temp = head;
newTemp = newNode;
while(temp!=null&&newTemp!=null){
// 只要出现了不相同的值则原链表不是回文链表
if(temp.val==newTemp.val){
temp = temp.next;
newTemp = newTemp.next;
}else{
return false;
}
}
return true;
}
- 回文数都是左右对称的,因此可以考虑只反转一半,如果左右两边完全相同则原链表是回文链表
先找到链表的中点确定要反转的部分(如果链表为奇数则反转中点节点之后的节点)如果为偶数则刚好反转一半节点
寻找链表中点:
// 找到链表的中点 (链表长度为偶数则找后面那个节点))
public ListNode midPoint(ListNode head){
ListNode fast = head;
ListNode slow = head;
// 链表长度为奇数的时候结束循环的时候fast.next为null
// 偶数的时候结束循环的时候fast为null
while(fast!=null&&fast.next!=null){
// 快慢节点 快的一次走两步 慢的一次一步
// 快的走到末尾了之后 慢的刚好在中间
fast = fast.next.next;
slow = slow.next;
}
// 如果为奇数则需要返回中间节点的下一个节点,中间节点不能反转
if(fast!=null){
slow = slow.next;
}
return slow;
}
反转找到的中间节点之后的节点:
// 反转slow节点以及之后的节点
public ListNode reverseM(ListNode head){
// 前一个节点
ListNode pre = null;
// 当前节点
ListNode cur = head;
// 下一个待反转节点
ListNode nex = head;
while(cur!=null){
nex = cur.next;
cur.next = pre;
pre = cur;
cur = nex;
}
return pre;
}
调用以上两个函数并执行最终的比较:
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
ListNode oldHead = head;
// 得到反转后那一半头结点
ListNode newHead = reverseM(midPoint(head));
// 遍历比较反转部分和未反转部分
while(newHead!=null){
// 出现不相等的值 则证明不是回文链表
if(newHead.val!=oldHead.val){
return false;
}
oldHead = oldHead.next;
newHead = newHead.next;
}
return true;
}
判断回文字符串
使用两个指针一个从头开始一个从尾部开始,同时开始遍历互相靠近
代码如下:
public static boolean isPalindrome(String str){
if(str.length()==0||str.length()==1){
return true;
}
int leftIndex = 0;
int rightIndex = str.length()-1;
while (leftIndex<=rightIndex){
if(str.charAt(leftIndex)!=str.charAt(rightIndex)){
return false;
}
leftIndex++;
rightIndex--;
}
return true;
}