> 文档中心 > 手撕链表笔试题(超详细思路过程)(第一期)

手撕链表笔试题(超详细思路过程)(第一期)

在这里插入图片描述


文章目录

  • 前言
  • 一、Leetcode--203移除链表元素
    • 1.1题目描述
    • 1.2思路讲解
    • 1.3代码实现
  • 二、Leetcode--83删除排序链表中的重复元素
    • 1.题目描述
    • 2.思路讲解
    • 3.代码实现
      • 3.1迭代
      • 3.2递归写法
  • 三、 Leetcode--82删除链表的重复元素||
    • 1.题目描述
    • 2.思路讲解
    • 3.代码实现
      • 3.1迭代
      • 3.2递归写法

前言

本篇博客我们一起来看看单链表的笔试题


一、Leetcode–203移除链表元素

1.1题目描述

在这里插入图片描述

1.2思路讲解

我们仔细看一下题目,题目需要删除所有值为val的节点,并返回新的头结点,也就是删除后链表的头结点,此时看到这道题跟链表的删除中的删除所有值为val的节点一样,重点讲一下,递归写法的思路,写递归的时候,我们一定要重视函数的语义
在这里插入图片描述
这个函数的要做的事就是:传入一个链表的头结点和待删除的值val,返回删除后的链表头结点,头结点之后的值为val的删除交给子函数
在这里插入图片描述

1.3代码实现

1.3.1迭代法

/** * 删除链表中所有值为val的结点 */public class Num203_RemoveLinkedListElement {    public ListNode removeElements(ListNode head, int val) { while(head != null && head.val == val){     ListNode x = head;     head = head.next;     x.next = null; } if (head == null){     return null; }else{     ListNode prev = head;     while (prev.next != null){  if (prev.next.val == val){      ListNode node  = prev.next;      prev.next = node.next;  }else{      prev = prev.next;  }     } } return head;    }

1.3.2虚拟头结点法

/**     * 虚拟头结点法     * @param head     * @param val     * @return     */    public ListNode removeElements(ListNode head, int val) { ListNode dummyHead = new ListNode(); //记得连接当前链表 dummyHead.next = head; ListNode prev = dummyHead; while(prev.next != null){     if (prev.next.val == val){  prev.next = prev.next.next;     }else{  prev = prev.next;     } } return dummyHead.next;    }

1.3.3递归写法

/**     * 传入一个链表的头结点head和待删除结点值val,就能删除删除所有值为val的结点,并返回删除后的头结点     * @param head     * @param val     * @return     */    public ListNode removeElements(ListNode head, int val) {    if (head == null){ return null;    }    //从第二结点开始的删除交给子函数    head.next = removeElements(head.next,val);    //只需要head的情况 if (head.val == val){     return head.next; } return head;    }

二、Leetcode–83删除排序链表中的重复元素

1.题目描述

在这里插入图片描述

2.思路讲解

读题之后,我们发现本题和链表的普通删除是不一样的,普通的链表删除,是给定我们一个值或者给定一个索引,然后再删除,但是本题没有给,而我们不知道哪些节点是重复的,这就需要我们自己
1.先找找到链表中的重复节点
2.然后再根据题目要求进行操作
3prev —> 指向待删除节点的前驱,而此时一个引用是无法找到重复元素的,那我们就要引入第二个引用cur,cur = prev.next;
4.如果prev.val == cur.val,说明这两个节点重复
5.让prev = head; cur = prev.next;当出现重复元素时,prev一定是第一个重复的元素,此时让cur引用向后移动,知道碰到第一个和prev不相等节点,我们让prev.next = cur,此时我们就删除了重复节点,而且还保留了一个prev的值,与题目相吻合
在这里插入图片描述

3.代码实现

3.1迭代

public class Num83_DeleteDuplicates {    public ListNode deleteDuplicates(ListNode head) { if (head == null || head.next == null){     return head; } ListNode prev = head; ListNode cur = prev.next; while(cur != null){     if (prev.val != cur.val){  prev = prev.next;     }else{  prev.next = cur.next;     }     cur = cur.next; } return head;    }}

3.2递归写法

public class Num83_DeleteDuplicates {   /**     * 递归     * 传入一个链表,就能删除其中值重复的结点,重复结点保留一次,并返回删除后的头结点     *     * @param head     * @return     */    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;    }}}

三、 Leetcode–82删除链表的重复元素||

1.题目描述

在这里插入图片描述

2.思路讲解

读完题,我们发现这道题和83号题非常相似,但是区别是
83号题是删除重复节点,并保留一个重复的节点
本题是删除所有的重复节点,重复节点一个不留
1.如果使用82题的思路,那么第一个重复节点删不掉,单链表的删除都是通过前驱节点删除 — > 前驱节点删不掉,所以prev不能指向待删除的节点
2.此时prev不能指向重复节点,要判断重复节点就得再引入两个个引用,三引用
3.cur.val == nxet.val —> 判断重复元素
在这里插入图片描述
1.此时我们定义一个虚拟头结点,因为虚拟头结点一定不是待删除的元素,让prev从dummyHead开始走,让cur = prev.next; next = cur.next;
2.当发现cur.val != next,val,三指针同时后移
3.当cur.val == next.val ,就让next一直向后移动,直到碰到第一个不重复的节点
当next走到第一个不重复的节点,那么prev到next之间的所有结点都是待删除结点
4.prev — > 指向第一个重复结点的前驱
next — > 指向最后一个重复结点的后继
prev 到 next之间的所有节点都是待删除的节点

3.代码实现

3.1迭代

public class Num82_DeleteDuplicates {    public ListNode deleteDuplicates(ListNode head) { ListNode dummyHead = new ListNode(); dummyHead.next = head; ListNode prev = dummyHead; ListNode cur = prev.next;      while (cur != null){   ListNode next = cur.next;   if (next == null){//当前链表只有一个结点//next走到空,所有节点删除完毕break;   }else{//此时链表至少右两个以上的结点if (cur.val != next.val){    //三指针后移    prev = prev.next;    cur = cur.next;}else{    //此时碰到重复元素,让next一直后移,直到碰到第一个不重复的结点    while(next != null && cur.val == next.val){ next = next.next;    }    //说明碰到第一个不重复的结点    prev.next = next;    cur = next;}   }      }      return dummyHead.next;    }}

3.2递归写法

public class Num82_DeleteDuplicates {   /**     * 传入一个排序链表,就能删除链表中所有的重复结点,返回删除后的链表的头结点     *     * @param head     * @return     */    public ListNode deleteDuplicates(ListNode head) { if (head == null || head.next == null) {     return head; } if (head.val != head.next.val) {     head.next = deleteDuplicates(head.next);     return head; } else {     ListNode nextHead = head.next;     while (nextHead != null && nextHead.val == head.val) {  nextHead = nextHead.next;     }     return deleteDuplicates(nextHead); }    }}

手撕链表笔试题(超详细思路过程)(第一期) 2022深度学习开发者峰会 手撕链表笔试题(超详细思路过程)(第一期) 5月20日13:00让我们相聚云端,共襄盛会!麦克风网