15, 19. 删除链表的倒数第 N 个结点
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
思路1: 暴力遍历删除
思路2: 使用栈结构
思路3: 双指针法
- 第一个指针指向第0个节点, 第二个指针指向n个节点,
- 两个指针同时往有移动,
- 当第二个指针指向最后一个节点当时候, 第一个指针必定指向倒数第n个节点的前一个节点
package com.shangguigu.dachang.algrithm.A05_linkedList;
import java.util.Stack;
/**
* @author : 不二
* @date : 2022/4/11-下午3:59
* @desc : 19. 删除链表的倒数第 N 个结点
* https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
**/
public class A51_removeNthFromEnd {
public static void main(String[] args) {
ListNode l1 = new ListNode(1);
ListNode l2 = new ListNode(2);
ListNode l3 = new ListNode(3);
ListNode l4 = new ListNode(4);
ListNode l5 = new ListNode(5);
l1.next = l2;
l2.next = l3;
l3.next = l4;
l4.next = l5;
// ListNode listNode = removeNthFromEnd_by_violance(l1, 1);
// ListNode listNode = removeNthFromEnd_by_stack(l1, 2);
ListNode listNode = removeNthFromEnd_by_twoPointer(l1, 2);
System.out.println("结果是:" + listNode);
}
/**
* 思路3:双指针法(一次遍历)
* 第一个指针指向0, 第二个指针指向n,
* 两个指针同时往有移动,
* 当第二个指针指向最后一个节点当时候, 第一个指针必定指向倒数第n个节点的前一个节点
*
*/
public static ListNode removeNthFromEnd_by_twoPointer(ListNode head, int n){
// first先走n步,然后first和second一起走,当first走到最后一个节点的时候,那么second必然指向倒数第n节点的前一个节点
ListNode first = head;
ListNode second = head;
for (int i = 0; i < n; i++) {
if (i < n - 1 && first.next == null) {
// 说明n大于链表长度, 没法删除,直接返回头节点即可
return head;
} else if (i == n - 1 && first.next == null) {
// 说明删除的刚好是头节点
return head.next;
} else {
first = first.next;
}
}
// 说明删除的是第一个节点后面的节点
while (first.next != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return head;
}
/**
* 思路2:使用栈结构!!!
*/
public static ListNode removeNthFromEnd_by_stack(ListNode head, int n){
Stack<ListNode> stack = new Stack<>();
ListNode currNode = head;
int length = 0;
while (currNode != null) {
length++;
stack.push(currNode);
currNode = currNode.next;
}
// 这里默认n不会超过链表的长度哈
if (n > length) {
return head;
} else if (n == length) {
return head.next;
} else {
// 这里要多走一步,找到前一个节点,方便删除指定节点
for (int i = 0; i <= n-1; i++) {
stack.pop();
}
stack.peek().next = stack.peek().next.next;
return stack.firstElement();
}
}
/**
* 思路1:暴力法:直接遍历找出长度,然后再遍历删除
*/
public static ListNode removeNthFromEnd_by_violance(ListNode head, int n) {
int length = 0;
ListNode theNode1 = head;
while (theNode1 != null) {
length++;
theNode1 = theNode1.next;
}
// System.out.println("长度是:" + length);
if (n > length) {
return head;
} else if (n == length) {
head = head.next;
return head;
} else {
ListNode theNode = head;
ListNode preNode = head;
for (int i = 0; i < length - n; i++) {
preNode = theNode;
theNode = theNode.next;
}
// 这里删除指定节点
preNode.next = theNode.next;
return head;
}
}
}