1、删除链表的倒数第n个结点
题目描述:给定一个链表,删除链表的倒数第n个结点,并返回链表的头指针。
示例:
输入:head = [1,2,3,4,5], n=2
输出:[1,2,3,5]
算法思路:首先我们是无法逆序遍历链表的,因此很难得到链表的倒数第n个元素,但是我们可以利用两个指针,而这两个指针之间的距离为n,当快指针遍历到链表尾时,慢指针刚好到达倒数第n个结点。这种方法最坏的情况是遍历整个链表1次。
或者我们按照最原始的想法,首先第一次顺序遍历链表,在这个过程中,统计链表的长度L;然后进行第二次遍历,一直到L-n个结点结束。这种方法最坏的情况是遍历整个链表2次。
上面两种方法时间复杂度都为O(n)。
代码实现:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy = ListNode()
dummy.next = head
slow = fast = dummy
for i in range(n):
fast = fast.next
while fast and fast.next:
slow = slow.next
fast = fast.next
slow.next = slow.next.next
return dummy.next
2、删除有序链表中重复的元素-I
题目描述:删除给定有序链表中的重复元素,使得链表中的所有元素都只出现一次。
示例:
输入:head = [1,1,2]
输出:[1,2]
算法思路:根据题目可知,相同的元素只留下一个,所以我们自然想到留下遍历链表的第一个元素,然后需要做的是跳过后面重复的元素。
具体做法:设置一个新的结点指向头结点,用于最终结果的返回;然后开始遍历链表,如果当前节点与下一个结点重复,那么跳过下一个结点,连接到下个结点的后一个结点;当遍历时的节点或者当前节点的下一个结点为空时,遍历结束。
该方法遍历一次链表,时间复杂度为O(n)。
代码实现:
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
public ListNode deleteDuplicates (ListNode head) {
ListNode dummy = head;
while(head !=null && head.next !=null){
if(head.val == head.next.val){
// 如果两个结点值相等,则跳过下一个元素,继续判断下下个元素是否重复
head.next = head.next.next;
} else{
// 否则当前节点无重复结点,继续向后遍历
head = head.next;
}
}
return dummy;
}
}
3、删除有序链表中重复的元素-II
题目描述:删除给定有序链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
示例:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
算法思路:为了避免删除头结点的情况,应该引入一个新的空结点作为新的头结点,然后逐个遍历链表结点,将其不断与它的后续结点相比较,如果重复,则开始删除,直到重复结点删除完,继续遍历。
该方法遍历一次链表,时间复杂度为O(n)。
代码实现:
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
public ListNode deleteDuplicates (ListNode head) {
// 定义一个空的结点指向头结点
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pred = dummy;
while(head != null){
// 开始遍历链表,比较当前结点与后续结点的元素是否相等
if(head.next != null && head.val == head.next.val){
// 相等则表明出现重复元素,开始删除重复结点
while(head.next != null && head.val == head.next.val){
head = head.next;
}
// 删除所有重复的元素,指向后面新的独立的结点
pred.next = head.next;
} else{
// 否则继续向后遍历
pred = pred.next;
}
head = head.next;
}
return dummy.next;
}
}