数据结构之链表练习题(leetCode)

本文详细介绍了链表的各种操作,包括删除链表中的重复元素、删除排序链表中的重复元素、反转链表、找到链表的中间节点、找到链表的倒数第k个节点、判断回文链表、合并两个有序链表、分割链表、找到相交链表的节点、检测环形链表以及反转链表的指定部分。涉及递归、双指针等技巧,展示了链表操作的多种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.移除链表元素(203)

题目: 给你一个链表的头节点 head 和一个整数val,请你删除链表中所有满足Node.val == val的节点,并返回新的头节点。
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
方法一:这道题是删除链表中所有等于val的元素,需要考虑两种情况。

  1. 头节点是要删除的节点,这时候我们循环判断head的值,但是head不能为空,这样就是链表中没元素了。
  2. 头节点确定不是要删除的结点,我们就遍历链表判断后面的值,因为我们找的是前驱结点,所以我们要保证待删除的结点不能为空,否则会造成空指针异常。造成了pre遍历到最后一个结点,已经没有要判断的结点了。
public ListNode removeElements(ListNode head, int val) {
   
    while(head != null && head.val == val){
   
        head = head.next;
    }
    for (ListNode pre = head; pre != null; pre = pre.next) {
   
        while(pre.next != null && pre.next.val == val) {
   
            pre.next = pre.next.next;
        }
    }
    return head;
}

方法二:递归
三步骤:首先,判断是否能拆分:这道题可以拆成head.val == val和剩下结点是否有val
其次:拆封后解决思路相同
最后:存在终止条件

  1. 理解函数的语义:传入头结点和待删除的值,函数就能删除所有等于val的元素
  2. 将链表分为头结点和其他结点,因为我们只能知道头结点。
  3. 把除头结点之后的链表的删除工作交给子函数运行,子函数就能把元素删除
  4. 判断头结点是否为需要删除的结点,若是,返回头结点的下一个结点;反之,返回头结点
public ListNode removeElements(ListNode head, int val) {
   
	//链表内没有元素,终止条件
    if (head == null){
   
        return null;
    }
    head.next = removeElements(head.next,val);
    //删除操作
    if (head.val == val){
   
        return head.next;
    }
    return head;
}

2.删除排序链表中的重复元素(83)

题目:给定一个已排序的链表的头head, 删除所有重复的元素,使每个元素只出现一次 。返回已排序的链表。
输入:head = [1,1,2]
输出:[1,2]
方法一:

  1. 这道题我们不知道要删除的元素是谁,所以我们需要引入两个指针去比较。
  2. 当pre.val == cur.val,说明pre是第一个重复的元素,所以我们保留这个元素,而cur是要删除的元素,所以pre.next = cur.next,然后让cur向后走,等于走一步删一步。
  3. 当pre.val!=cur.val,说明他们不是要删除的元素,一起向后走。直到cur==null,循环完毕,返回头结点。
public ListNode deleteDuplicates(ListNode head) {
   
    //当链表为空或者只有一个元素的时候,不可能有重复的元素
    if (head == null || head.next == null){
   
        return head;
    }
    ListNode pre = head;
    ListNode cur = pre.next;
    while(cur != null){
   
        if (pre.val != cur.val) {
   
            pre = pre.next;
            cur = cur.next;
        } else {
   
            pre.next = cur.next;
            cur = cur.next;
        }
    }
    return head;
}

方法二:递归

  1. 将题目拆封成头结点和之后的结点两部分。
  2. 理解函数语义:一个有序的链表,传入头结点,可以将重复元素删除,只保留一个重复的元素,返回删除后的头结点
  3. 第二个结点之后的删除交给子函数去运行。
  4. 由于我们只知道头结点,所以我们将当前的头结点和返回后的头结点相比较,如果相等,就把当前头结点删了,返回head.next;反之,返回head。
public ListNode deleteDuplicates(ListNode head) {
   
    if (head == null || head.next == null) {
   
        return head;
    }
    head.next = deleteDuplicates(head.next);
    if (head.val == head.next.val) {
   
        return head.next;
    }
    return head;
}

在这里插入图片描述

3.删除排序链表中的重复元素 II(82)

题目:给定一个已排序的链表的头head,删除原始链表中所有重复数字的节点,只留下不同的数字。返回已排序的链表 。
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
方法一:

  1. 这里引入了三个指针.如果两个指针的话,当pre指向重复元素的话,就删不掉了。因为重复元素都要删除,所以pre要指向不重复的元素,我们就让剩下两个指针判断结点是否重复。
  2. 当cur.val != next.val,三指针同时向后移动
  3. 当cur.val == next.val,循环让next向后移动,移动到第一个和cur不相等的元素,意味着pre之后next之前的元素都是要删除的元素。所以pre.next = next把元素删除
  4. 删除后cur和next向后移动一个结点。pre不能向后移动,因为有可能cur和next依旧相等。
public ListNode deleteDuplicates(ListNode head) {
   
    ListNode dummyHead = new ListNode();
    dummyHead.next = head;
    ListNode pre = dummyHead;
    ListNode cur = pre.next;
    while(cur != null) {
   
        ListNode next= cur.next;
        if (next == null){
   
            //链表内只有一个节点或者链表遍历完了
            break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值