删除节点
-
题目:如果给定一个链表,请问如何删除链表中的倒数第K个节点?假设链表中的节点总数为N,那么1≤K≤N。要求只能遍历链表一次
-
举例:输入如下链表a,删除倒数第2个节点之后得到链表b
链表a: 1-->2-->3-->4-->5-->6 链表b: 1-->2-->3-->4-->6
思路
- 如果可以遍历两次,那么这个问题就会变得简单不少:
- 第一次遍历获取链表总结点数n(题目为例:n = 6)
- 第二次遍历直接找出链表的第n-k个节点(题目为例:n-k = 6-2 = 4),并把该节点(倒数k+1)的next指向其next.next(倒数k-1)节点,即可删除倒数第k个节点
- 可以通过设置快慢双指针实现
- 快指针先走k步,慢指针保持不动
- 当快指针从k+1步继续往后走时,慢指针开始移动
- 当快指针到达链表末尾时,慢指针此时会到达倒数k+1个节点
- 此时删除第k个节点即可(参考第1.2步)
实现
- 链表:
public class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
@Override
public String toString() {
return val + "";
}
/**
* 打印链表方法
* @param head
*/
public static void printNodeList(ListNode head) {
StringBuilder res = new StringBuilder();
while(head != null){
res.append(head).append("->");
head = head.next;
}
res.append("NULL");
System.out.println(res);
}
}
- 解答:
/**
* 遍历一次删除倒数第k个节点
*/
public class DeleteKthNodeFromEnd {
public static ListNode removeKthNodeFromEnd(ListNode head, int k) {
//设置头节点,为慢指针设置起点
ListNode dummy = new ListNode(0);
dummy.next = head;
//定义快慢指针
ListNode front = head;
ListNode back = dummy;
//初始化快指针
for (int i = 0; i < k; i++) {
front = front.next;
}
//同时遍历快、慢指针
while (front != null) {
front = front.next;
back = back.next;
}
//删除第k个元素
back.next = back.next.next;
//返回原始头节点
return dummy.next;
}
}
验证
-
实例验证:
public static void main(String[] args) { ListNode node1 = new ListNode(1); ListNode node2 = new ListNode(2); ListNode node3 = new ListNode(3); ListNode node4 = new ListNode(4); ListNode node5 = new ListNode(5); ListNode node6 = new ListNode(6); node1.next = node2; node2.next = node3; node3.next = node4; node4.next = node5; node5.next = node6; ListNode.printNodeList(node1); removeKthNodeFromEnd(node1, 3); System.out.println("======================="); ListNode.printNodeList(node1); }
-
结果:
1->2->3->4->5->6->NULL ===================== 1->2->3->5->6->NULL
详解(DEBUG过程解析)
-
初始化链表及dummy起点,此时快指针指向1 ,慢指针指向0
0-->1->2->3->4->5->6->NULL | | | 慢 快
-
初始化快指针后:
此时:
0-->1->2->3->4->5->6->NULL | | | 慢 快
-
快慢指针同时遍历,当快指针到null时,慢指针为:
此时:
0-->1->2->3->4->5->6->NULL | | | 慢 快
-
删除第k个节点
-
最后返回原始头节点即可: