题目描述:
描述来源于官方截图
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
// 直观的办法,官方的解法一就是这个。
// 官方技巧:加一个哑节点,就可以将只有一个节点或者删除头结点的情况和普通情况统一起来,更加简洁。
// public ListNode removeNthFromEnd(ListNode head, int n) {
// int nodeN=1;
// ListNode temp=head;
// //先点出有几个节点
// while(temp.next!=null){
// temp=temp.next;
// nodeN++;
// }
// // 只有一个节点且删除的是这个,直接返回null
// if(nodeN==1&&n==1){
// return null;
// }
// // 有nodeN个且删除倒数第nodeN个,就是删除头结点并返回
// if(nodeN==n){
// head=head.next;
// return head;
// }
// temp=head;
// int j=nodeN-n;
// int p=1;
// while(true){
// if(p==j){
// break;
// }
// temp=temp.next;
// p++;
// }
// temp.next=temp.next.next;
// return head;
// }
// 官方解法1
// public ListNode removeNthFromEnd(ListNode head, int n) {
// ListNode dummy = new ListNode(0);
// dummy.next = head;
// int length = 0;
// ListNode first = head;
// while (first != null) {
// length++;
// first = first.next;
// }
// length -= n;
// first = dummy;
// while (length > 0) {
// length--;
// first = first.next;
// }
// first.next = first.next.next;
// return dummy.next;
// }
// 官方解法二是用双指针,先让一个指针和另一个隔开,然后让同时运动,直到一个到结尾。那么另一个就是要删除节点的前驱结点。使用双指针的效率和遍历两遍是一样的,双指针其实也是遍历了两遍。自觉地比官方解法二更清晰
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode first=dummy;
ListNode second=dummy;
for(int i=0;i<n;i++){
first=first.next;
}
while(first.next!=null){
second=second.next;
first=first.next;
}
second.next=second.next.next;
return dummy.next;
}
}