写在前面
题目传送门:leetcode链表题
一、自己写的代码
自己的思路是暴力破解的方法,也就是将倒数便为正数,再去匹配,两次循环遍历
当然,自己最后没有实现,因为没有考虑到哑结点,有些测试用例无法通过
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// 链表只有一个元素
if(head == null){
return null;
}
//计算有效的节点数
int length = 0;
ListNode temp = head;
while(temp != null){
length++;
temp = temp.next;
}
// 转换逻辑
n = length - n;
temp = head.next;
ListNode cur = temp;
for(int i = 0; i <= n; i++){
cur = temp;
// 后移
temp = temp.next;
if(i == n - 1){
cur.next = temp.next;
temp = cur.next;
}
}
return head;
}
}
二、官方解法
在对链表进行操作时,一种常用的技巧是添加一个哑节点(dummy node),它的 next 指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了。
例如,在本题中,如果我们要删除节点 y,我们需要知道节点 y 的前驱节点 x,并将 x 的指针指向 y 的后继节点。但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了哑节点,那么头节点的前驱节点就是哑节点本身,此时我们就只需要考虑通用的情况即可。
特别地,在某些语言中,由于需要自行对内存进行管理。因此在实际的面试中,对于「是否需要释放被删除节点对应的空间」这一问题,我们需要和面试官进行积极的沟通以达成一致。下面的代码中默认不释放空间。
解法一:计算链表长度
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// 哑节点
ListNode dummpy = new ListNode(0,head);
// 获取长度
int length = getLen(head);
ListNode cur = dummpy;
for(int i = 0; i < length - n; i++){
// 后移
cur = cur.next;
}
// 删除操作
cur.next = cur.next.next;
// 返回遍历的头结点(除去哑结点)
ListNode ans = dummpy.next;
return ans;
}
// 获取有效长度
public int getLen(ListNode head){
int length = 0;
while(head != null){
length++;
head = head.next;
}
return length;
}
}
解法二:快慢双指针
思路:
1、定义两个指针,然后快指针fast领先慢指针slow n 个节点
2、当快指针遍历到最后时,就可以停止两个指针向下遍历了。然后就可以堆满指针的位置进行删除操作了
自己的写法
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// 哑节点
ListNode dummpy = new ListNode(0,head);
// 快节点
ListNode fast = head;
// 慢节点
ListNode slow = dummpy;
while(true){
if(fast.next == null){
break;
}
// 让快指针领先n个位置
if(n > 0){
n--;
}else{
// 慢指针后移
slow = slow.next;
}
// 快指针后移
fast = fast.next;
}
// 删除节点
slow.next = slow.next.next;
return dummpy.next;
}
}
官方写法
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode first = head;
ListNode second = dummy;
for (int i = 0; i < n; ++i) {
first = first.next;
}
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
ListNode ans = dummy.next;
return ans;
}
}