给你一个链表,删除链表的倒数第
n
个结点,并且返回链表的头结点。
摘自: 力扣
这个问题很简单:就是遍历一遍链表,确定链表一共多少个节点,算出是链表第几个节点是倒数第二个节点,找出要删除节点的上一个节点,然后上一个节点的指针指向要删除节点的下一个节点即可。正常解题思路,也是O(n)级别算法。(因为有可能需要删除的是头结点,所以使用虚拟头结点)
public ListNode removeNthFromEnd(ListNode head, int n) {
int i = 0;
ListNode dummmyHead = new ListNode(0, head);
ListNode cur = dummmyHead;
while (cur != null){
i++;
cur = cur.next;
}
i = i - 1;
i = i - n;
ListNode pre = dummmyHead;
for(int j = 0; j < i; j++){
pre = pre.next;
}
pre.next = pre.next.next;
return dummmyHead.next;
}
但是能不能更好些呢,一次遍历可不可以呢。这个怎么优化呢,一次遍历。。。。
也就是说,我们一次遍历需要找到倒数n节点的上一个节点。
怎么找到这个节点,怎么确定这个节点呢,
- 首先需要一个参考节点,也就是最后一个节点,
- 然后根据n这个参数,我们需要一个关系表达式,帮我们锁定这个节点。
- 也就是说,我们需要两个指针,从头开始遍历到链表结束时,一个指针指向末尾,一个指针指向这个节点即可。这样一次遍历就可以找到。
- 至于他们之间关系,需要与n有关的一个表达式。
首先确定表达式关系:假设两个指针:a、b;a指向欲删除节点的上一个节点。b指向最后一个节点的下一个节点 null;
则:b = a + n + 1;
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummmyHead = new ListNode(0, head);
ListNode a = dummmyHead;
ListNode b = dummmyHead;
for(int i = 0 ; i < n + 1; i++ ){
b = b.next;
}
while (b != null){
b = b.next;
a = a.next;
}
a.next = a.next.next;
return dummmyHead.next;
}