LeeCode题目:删除链表结点


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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值