public class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
//8.对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。测试样例:1->2->2->1;返回:true
**//方案一:遍历链表,求长度,然后求中间节点,再逆置!**
public boolean chkPalindrome(ListNode A) {
// 此处只是假设算回文
if (A == null){
return true;
}
// 只有一个元素, 就是回文
if (A.next == null){
return true;
}
// 1. 找中间节点
int len = size(A);
int steps = len / 2;
ListNode B = A;
for (int i = 0; i < steps; i++) {
B = B.next;
}
ListNode prev = null;
ListNode cur = B;
while (cur != null){
ListNode next = cur.next;
if (next == null){
//使用 B 指向新链表的头部
B = cur;
}
cur.next = prev;
// 更新 prev, 更新 cur
prev = cur;
cur = next;
}
// 3. 对比两个链表内容是否相同
while (B != null){
if (A.val != B.val){
// 对应元素不相等, 一定不是回文
return false;
}
A = A.next;
B = B.next;
}
return true;
}
//计算链表的长度
public int size(ListNode head){
int size = 0;
//遍历链表,获取长度
for (ListNode cur = head;cur != null;cur = cur.next) {
size++;
}
return size;
}
**//方案二:用快慢(快指针一次走两步,慢指针一次走一步)指针求中间节点,然后从中间节点之后的节点开始逆置即修改引用的指向**
**思路如下:**
**1、定义两个引用,目的:找到单链表的中间位置
2、进行翻转,翻转的是后半部分
3、一个head从头开始走,slow从尾巴开始走
4、只要发现对应的data不相同,那么就不是回文**
public boolean chkPalindrome() {
if (this.head == null) {
return false;
}
if (this.head.next == null) {
return true;
}
Node fast = this.head;
Node slow = this.head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//2.翻转
Node p = slow.next;
while (p != null) {
Node pNext = p.next;
p.next = slow;
slow = p;
p = pNext;
if (p != null) {
pNext = p.next;
}
}
//3.进行判断
while (this.head != slow) {
//奇数个数情况
if (this.head.data != slow.data) {
return false;
}
//偶数
if (this.head.next == slow) {
return true;
}
this.head = this.head.next;
slow = slow.next;
}
return true;
}
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。测试
最新推荐文章于 2023-01-19 08:30:00 发布