We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
请判断一个链表是否为回文链表。 示例 1: 输入: 1->2 输出: false
请判断一个链表是否为回文链表。 示例 1:
输入: 1->2 输出: false
示例 2: 输入: 1->2->2->1 输出: true
示例 2:
输入: 1->2->2->1 输出: true
进阶: 你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
这个题目本身并算不上难题, O(n) 的时间复杂度也是没得跑,关键就是空间复杂度了,那么先上一个需要 O(n) 空间复杂度的解法:
public boolean isPalindrome(ListNode head) { ListNode slow = head; List<ListNode> list = new ArrayList<>(); while (slow.next != null) { list.add(slow); slow = slow.next; } Collections.reverse(list); ListNode l = head; for (ListNode n : list) { if (n.val != l.val) { return false; } l = l.next; } return true; }
这基本是入门程序员都可以写出来的,所以这个题目加了一个“进阶”,只使用常数空间。
链表相关的题目都经常用到的一快一慢双指针,通过这个双指针,我们可以定位到链表的中间位置。但是因为双指针的起点的不同,以及链表长度的奇偶不同,会有一些细节上的差异。比如如下情况,其中 N 表示一个节点,fn 表示快指针 fast 第 n 步的位置,sn同理
N
fn
fast
n
f0--------f1--------f2 N -> N -> N -> N -> N -> null s0--s1---s2
链表长度为奇数的情况下,快指针指向最后一个元素,慢指针指向中间元素;
f0--------f1--------f2---------f3 N -> N -> N -> N -> N -> N -> null s0--s1---s2---s3
链表长度为偶数的情况下,快指针指向 null,慢指针指向第 n/2 + 1 个元素;
null
n/2 + 1
很多算法都有“拿时间换空间”或者“拿空间换时间”的说法,在这个题里,空间减少的同时,因为相关操作的减少,所以时间上反而也减少了。 首先是通过快慢指针定位中间位置,然后比较前半段和后半段了,因为回文的特殊性,我们需要反转某半段链表,才能方便的进行比较。代码如下:
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public boolean isPalindrome(ListNode head) { // 参数校验 if (head == null || head.next == null) { return true; } // 寻找中间位 ListNode fast = head; ListNode slow = head; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; } ListNode p2; // 确定后半段的起点 if (fast == null) { // 链表长度为偶数,slow 指向后半段的开始 p2 = slow; } else { // 链表长度为奇数,slow 指向中间值 p2 = slow.next; } // 反转前半段 ListNode pre = null; ListNode cur = head; while (cur != slow) { // 保存当前节点的下一个 ListNode next = cur.next; // 下一个改为指向前一个 cur.next = pre; // pre = cur; // 处理下一个 cur = next; } // 比较 while (pre != null) { if (pre.val != p2.val) { return false; } pre = pre.next; p2 = p2.next; } return true; } }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
题目描述
空间复杂度 O(n) 的解法
这个题目本身并算不上难题, O(n) 的时间复杂度也是没得跑,关键就是空间复杂度了,那么先上一个需要 O(n) 空间复杂度的解法:
这基本是入门程序员都可以写出来的,所以这个题目加了一个“进阶”,只使用常数空间。
快慢指针
链表相关的题目都经常用到的一快一慢双指针,通过这个双指针,我们可以定位到链表的中间位置。但是因为双指针的起点的不同,以及链表长度的奇偶不同,会有一些细节上的差异。比如如下情况,其中
N
表示一个节点,fn
表示快指针fast
第n
步的位置,sn同理链表长度为奇数的情况下,快指针指向最后一个元素,慢指针指向中间元素;
链表长度为偶数的情况下,快指针指向
null
,慢指针指向第n/2 + 1
个元素;空间复杂度 O(1) 的解法
很多算法都有“拿时间换空间”或者“拿空间换时间”的说法,在这个题里,空间减少的同时,因为相关操作的减少,所以时间上反而也减少了。
首先是通过快慢指针定位中间位置,然后比较前半段和后半段了,因为回文的特殊性,我们需要反转某半段链表,才能方便的进行比较。代码如下:
The text was updated successfully, but these errors were encountered: