在单链表和双链表中删除倒数第k个结点

时间:2023-03-09 09:13:55
在单链表和双链表中删除倒数第k个结点

题目:

分别实现两个函数,一个可以删除单链表中倒数第K个节点,另一个可以删除双链表中倒数第K个节点。

要求:

如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1)。

解答:

让链表从头走到尾,每移动一步,就让K值减一,

示例:

第一种情况:

在单链表和双链表中删除倒数第k个结点

链表走到结尾时,如果K值大于0,说明不用调整链表,因为链表根本没有倒数第K个节点,此时将原链表直接返回即可;

第二种情况:

在单链表和双链表中删除倒数第k个结点

链表走到结尾时,如果K值等于0,说明链表倒数第K个节点就是头结点,此时直接返回head.next,相当于删除了头结点。

第三种情况:(当链表走到结尾时,当K的值小于零时,)

在单链表和双链表中删除倒数第k个结点

K< 0 时的处理方法:

在单链表和双链表中删除倒数第k个结点

链表长度为N,要删除倒数第K个节点,那么倒数第K个节点的前一个结点就是第N-K个节点。在第一次遍历之后,K的值变为了K-N。第二次遍历时,K的值不断加1.加到0就停止遍历,所在的位置就是第N-K个节点的位置。

public class Problem02_RemoveLastKthNode {

//    单链表
public static class Node {
public int value;
public Node next; public Node (int data){
this.value = data;
}
} // 双链表
public static class DoubleNode{
public int value;
public DoubleNode last;
public DoubleNode next; public DoubleNode (int data) {
this.value = data;
}
} // 删除单链表中倒数第K个结点
/* 1. 异常情况考虑:---- 链表为空,K值<1, 返回头结点
* 2. 其他(链表非空,K值>0) 策略:从头结点开始往后k--
* 2.1. 到达链表尾部时(cur = null), k>0, 则不存在K结点;
* 2.2. 到达链表尾部时(cur = null), k=0, 则头结点head就是K结点;
* 2.3. 到达链表尾部时(cur = null), k<0, 则需要找到删除K结点的前一个结点;
* 详情:
* 重新从头结点开始,每移动一步,就让K值加1;
* 当k=0时,移动停止,移动到的结点就是要删除的结点的前一个结点
*/
public static Node removeLastKthNode(Node head, int lastKth){
if (head == null || lastKth < 1){
return head;
}
Node cur = head;
while(cur != null) {
lastKth--;
cur = cur.next;
}
if (lastKth == 0){
head = head.next;
}
if (lastKth < 0){
cur = head;
while( ++lastKth != 0){
cur = cur.next;
}
cur.next = cur.next.next;
}
return head;
} // 删除双链表中倒数第K个结点(同单链表,注意last指针的重连即可)
public static DoubleNode removeLastKthNode(DoubleNode head, int lastKth){
if (head == null || lastKth < 1){
return head;
}
DoubleNode cur = head;
while(cur != null){
lastKth--;
cur = cur.next;
}
if(lastKth == 0){
head = head.next;
head.last = null;
}
if (lastKth < 0){
cur = head;
while(++lastKth != 0){
cur = cur.next;
}
DoubleNode newNext = cur.next.next;
cur.next = newNext;
if (newNext != null) {
newNext.last = cur;
}
}
return head;
} // 打印链表值函数
public static void printLinkedList(Node head) {
System.out.println("Linked list: ");
while(head != null){
System.out.println(head.value + " ");
head = head.next;
}
System.out.println(); } public static void printDoubleLinkedList(DoubleNode head){
System.out.println("DoubleLinked list: ");
DoubleNode end = null;
while (head != null) {
System.out.println(head.value + " ");
end = head;
head= head.next;
}
System.out.println("**********");
while(end != null) {
System.out.println(end.value + " ");
end = end.last;
}
System.out.println();
}
public static void main(String[] args) {
Node head1 = new Node(1);
head1.next = new Node(2);
head1.next.next = new Node(3);
head1.next.next.next = new Node(4);
head1.next.next.next.next = new Node(5);
head1.next.next.next.next.next = new Node(6);
printLinkedList(head1);
head1 = removeLastKthNode(head1, 3);
// head1 = removeLastKthNode(head1, 6);
// head1 = removeLastKthNode(head1, 7);
printLinkedList(head1); DoubleNode head2 = new DoubleNode(1);
head2.next = new DoubleNode(2);
head2.next.last = head2;
head2.next.next = new DoubleNode(3);
head2.next.next.last = head2.next;
head2.next.next.next = new DoubleNode(4);
head2.next.next.next.last = head2.next.next;
head2.next.next.next.next = new DoubleNode(5);
head2.next.next.next.next.last = head2.next.next.next;
head2.next.next.next.next.next = new DoubleNode(6);
head2.next.next.next.next.next.last = head2.next.next.next.next;
printDoubleLinkedList(head2);
head2 = removeLastKthNode(head2, 3);
// head2 = removeLastKthNode(head2, 6);
// head2 = removeLastKthNode(head2, 7);
printDoubleLinkedList(head2);
} }

结果:

Linked list:
1
2
3
4
5
6 Linked list:
1
2
3
5
6 DoubleLinked list:
1
2
3
4
5
6
**********
6
5
4
3
2
1 DoubleLinked list:
1
2
3
5
6
**********
6
5
3
2
1