要移动倒数第n个, 就要来到倒数第n + 1个node处. 那么first和second的距离就是n个间隔, 因此second要先走n步. 然后再一起走, 等到second到达倒数第一个node时, first就在倒数第n + 1个node处.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode first = head; for (int i = 0; i < n; i++) { first = first.next; } if (first == null) return head.next; ListNode second = head; while (first.next != null) { first = first.next; second = second.next; } second.next = second.next.next; return head; } }
|
两个指针就行了, 但是第17行需要我们额外判断一下, 因为我们想让second处于的位置是要被remove的node的前一个位置, 那如果要remove head呢? 此时second就没地方去了, 因此要额外判断.
时间复杂度: O(n)
空间复杂度: O(1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode first = dummy; for (int i = 0; i < n; i++) { first = first.next; } ListNode second = dummy; while (first.next != null) { first = first.next; second = second.next; } second.next = second.next.next; return dummy.next; } }
|
这个solution就是解决如果要remove head的情况, 我们手动加一个dummy node, 让它指向head. first和second都从dummy出发, 逻辑还是一样让first先走n步, 这样first和second之间就有n个间隔. 那么即使要remove head, first会走n步来到最后一个node, 此时它的next就是null, second在dummy, 此时second和first相隔n个间隔, second在要被remove的node的前一个位置. 此时直接remove即可.
时间复杂度和空间复杂度不变.