题目:
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
题目中要求最好将链表只遍历一次才可以,但是根据分析可知,链表题无非三种方法:哑节点、栈、快慢指针(双指针)。其中哑节点理解起来简单,先通过遍历列表得到length后再进行删除操作,但是仍需要两次遍历;第二种栈方法即将所有链表压进栈,再通过出栈n次找到要删除的节点,仍是遍历两次;第三种方法也近乎遍历两次,所以一次遍历的要求不能满足。
所以选择第一种方法解决最有效。
首先getListLength自编函数得到链表长度(老生常谈,三十秒打完)
下一步就是关键的找节点了,其实这里隐藏着一个坑,如果简单的变为向后移动length - n个节点,然后再curr.next = curr.next.next;时,当只有一个节点的链表就会出错。
所以正确的是将哑节点设置在head的前一个,并且将curr初始化为dummyNode就不会出现错误了,这里就避免了只有单个节点的问题。
完全代码如下:
public class no_19 {
public static void main(String[] args) {
ListNode head = new ListNode(1, new ListNode(2, new ListNode(3,
new ListNode(4, new ListNode(5)))));
ListNode re = removeNthFromEnd(head, 2);
while (re != null) {
System.out.println(re.val);
re = re.next;
}
}
public static ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyNode = new ListNode(0, head);
int length = getListLength(head);
ListNode curr = dummyNode;
for (int i = 0; i < length - n; i++) {
curr = curr.next;
}
curr.next = curr.next.next;
return dummyNode.next;
}
public static int getListLength(ListNode head) {
int length = 0;
while (head != null) {
length++;
head = head.next;
}
return length;
}
}
根据情况自己调整吧