给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:给定的 n 保证是有效的。
进阶:你能尝试使用一趟扫描实现吗?
如果不要求使用一趟扫描就实现结点的删除,暴力的方法可以先读取链表中所有的结点到数组中,然后再移除数组中倒数第n个值,最后使用数组再建立新的链表即可。但是这样的方式相当于需要扫描两次链表。
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
if head == None: return None
if head.next == None and n == 1: return None
l =0
cur = head
while cur:
l += 1
cur = cur.next
r = []
cur = head
while cur:
r.append(cur.val)
cur = cur.next
r = r[: l - n] + r[l - n + 1:]
newHead = ListNode(-1)
cur = newHead
for i in r:
node = ListNode(i)
cur.next = node
cur = cur.next
return newHead.next
更好的方式是在扫描的过程中实现结点的删除,链表的倒数第n个结点即正数的第l - n
个结点:
-
如果
l - n == 0
,则直接返回head.next
即可 -
否则,设置
cur
指向head
,同时设置index寻找l - n - 1
- 如果
index == l - n - 1
,则执行cur.next = cur.next.next
,跳出循环返回head
- 否则
cur = cur.next
,index += 1
继续往后寻找
- 如果
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
if head == None: return None
if head.next == None and n == 1: return None
# 获取链表长度
p = head
l = 0
while p:
l += 1
p = p.next
k = l - n
if k == 0:
head = head.next
return head
else:
index = 0
cur = head
while cur:
# print(index, cur.val)
if index == k - 1:
cur.next = cur.next.next
cur = cur.next
break
cur = cur.next
index += 1
return head
链表问题同样可以尝试用双指针法进行解决,设置新节点链接到head
前面,然后设置指针slow
和fast
分别指向新链表的头结点。首先让fast
多走n
步,然后slow
和fast
同时往后走,直到fast.next == None
。此时slow
所指向的节点是要删除结点的前驱结点,执行slow.next = slow.next.next
,删除倒数第n个结点,返回h.next
。
AC code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
if head == None: return None
if head.next == None and n == 1: return None
h = ListNode(0)
h.next = head
slow, fast = h, h
for i in range(n):
fast = fast.next
while fast.next:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return h.next
Java解题代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode slow = head;
ListNode fast = head;
// 先让快指针走n步
while(n-- > 0){
fast = fast.next;
}
// 判断一种特殊情况:如果此时fast == null,说明要删除的就是它
// 直接返回head.next
if(fast == null){
return head.next;
}
// 否则快慢指针一起走
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
// fast走到头时,slow位于倒数第n + 1个节点处
// 删除倒数第n个节点,slow.next = slow.next.next
slow.next = slow.next.next;
return head;
}
}