题目19:删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
/**
* 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; }
* }
*/
//思路1:首先遍历这个链表得到长度,然后遍历到要删除节点的前一个节点即可,注意小技巧:我们可以定义指针为头节点的前一个节点,因为这样当我们删除头节点时,我们不用分情况
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//计算长度
int length = len(head);
//计算完长度,我们计算要删除节点的前一个的位置
int index = length - n;
//定义指针,用于删除节点
ListNode pre = new ListNode(0 , head);
//用于返回
ListNode pre1 = pre;
for(int i = 0 ; i<index ; i++){
pre = pre.next;
}
pre.next = pre.next.next;
//返回数组,不能返回头节点,万一头节点是删除节点呢
return pre1.next;
}
public int len(ListNode head){
ListNode temp = head;
int count = 0;
while(temp!=null){
count++;
temp = temp.next;
}
return count;
}
}
//思路2:第二种方法,我们可以用栈来解决问题,先入后出,遍历字符串,把每一个字符放入到栈中,然后再拿出n个
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//先定义一个栈
Deque<ListNode> stack = new LinkedList<ListNode>();
//用于找到删除节点的前一个节点
ListNode pre = new ListNode(0,head);
//用于返回
ListNode pre1 = pre;
//然后遍历字符串将其全都放入到栈中(一定要注意放入的时候一定要放入头节点的前一个节点))
while(pre!=null){
stack.push(pre);
pre = pre.next;
}
//然后我们取出后面的n个
for(int i=0 ; i< n ; i++){
stack.pop();
}
//现在栈中嘴上的节点就是删除节点的前一个节点
ListNode cur = stack.peek();
//删除当前节点
cur.next = cur.next.next;
//返回当前节点
return pre1.next;
}
}
//思路3:快慢指针,第一个指针先走n步,然后两个指针一起走,一直到前一个指针遍历结束
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//定义一个指针好返回
ListNode pre = new ListNode(0,head);
//定义两个指针
ListNode first = head;
ListNode second = pre;
for(int i=0 ; i<n ;i++){
first = first.next;
}
while(first!=null){
first = first.next;
second = second.next;
}
//这时候second指的就是要删除节点的前一个
second.next =second.next.next;
//然后返回第一个节点
return pre.next;
}
}