234回文链表
# 描述
难度:简单
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶: 你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/palindrome-linked-list 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# 思路
# 方法一 :辅助栈、hashmap、数组、Map
字符串回文大家都知道怎么做了,这里也一样可以用数组、List、HashMap、栈去存放节点的值,然后遍历前半部分,和后后半部分逐一进行比较。
这种方法比较简单,但是 时间复杂度是 O(2N) 和 空间复杂度是 O(N)
# 方法二:反转链表
可以将后半部分链表反转,或者把后半部分的值入栈。
你需要先了解反转链表的实现,用到了双指针:206-翻转链表
步骤是:
- 找到中点,可以利用双指针,慢指针走1步,快指针走2步,快指针走到尾部NULL,那么慢指针刚好就走到了中点
- 反转中点.next 之后(也就是后半部分)的链表。
- 前半部分链表和反转的后半部分链表 进行比较。
见代码。
# 题解
public class 回文链表234 {
static class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public static void main(String[] args) {
ListNode listNode = new ListNode(1);
listNode.next = new ListNode(2);
listNode.next.next = new ListNode(3);
listNode.next.next.next = new ListNode(2);
listNode.next.next.next.next = new ListNode(1);
System.out.println(isPalindrome(listNode));
System.out.println(isPalindrome2(listNode));
System.out.println(isPalindrome3(listNode));
}
/**
* 辅助Map,当然放在List也一样
* 时间复杂度 O(2N)
* 空间复杂度 O(N)
*
* @param head
* @return
*/
static boolean isPalindrome(ListNode head) {
if (head == null) {
return false;
}
Map map = new HashMap<Integer, Integer>();
int i = 0;
while (head != null) {
map.put(i++, head.val);
head = head.next;
}
for (int j = 0; j < map.size() / 2; j++) {
if (map.get(j) != map.get(map.size() - j - 1)) {
return false;
}
}
return true;
}
/**
* 辅助栈
*
* @param head
* @return
*/
static boolean isPalindrome2(ListNode head) {
//面腾讯遇到了这道题,当时想到用的栈,回来看发现之前没这么做过,来做一做
LinkedList<Integer> stack = new LinkedList<Integer>();
ListNode tmp = head;
//把全部节点的值入栈
while (tmp != null) {
stack.push(tmp.val);
tmp = tmp.next;
}
//传递一个指针到tmp2,指向head头部
ListNode tmp2 = head;
while (tmp2 != null) {
if (tmp2.val != stack.pop()) {
return false;
}
tmp2 = tmp2.next;
}
return true;
}
/**
* 翻转后半部分的链表
* @param head
* @return
*/
static boolean isPalindrome3(ListNode head) {
if (head == null) {
return true;
}
// 找到前半部分链表的尾节点并反转后半部分链表
ListNode firstHalfEnd = endOfFirstHalf(head);
//反转链表
ListNode secondHalfStart = reverseList(firstHalfEnd.next);
// 判断是否回文
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while (result && p2 != null) {
if (p1.val != p2.val) {
result = false;
}
p1 = p1.next;
p2 = p2.next;
}
// 还原链表并返回结果
firstHalfEnd.next = reverseList(secondHalfStart);
return result;
}
private static ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
private static ListNode endOfFirstHalf(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
上次更新: 2026-03-28 17:00:16