删除链表中的结点类型题JAVA解答
Posted 劭兮劭兮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了删除链表中的结点类型题JAVA解答相关的知识,希望对你有一定的参考价值。
最近,总是遇到关于单链表中的结点删除类型题,乖乖也给我反应不是特别懂这么多类型题,于是就特意总结了以下,某个小乖乖要好好看看啊!
本人小白一个,可能还有很多问题总结得不到位,还请大家指教!
文章目录
AcWing28:在O(1)时间删除链表结点
单链表中删除某个结点的时候,只能通过前驱节点的next指针改变指向来删除该结点;
输入:单链表 = [1, 4, 6, 8],node = 6
删除结点:删除第二个结点,即删除值为 6 的结点
输出:[1, 4, 8]
解题方法
我们如果让该结点的next结点代替要删除的结点,也可完成删除该结点的操作;
将下一结点的值赋值给本结点,然后将本结点的next指针指向下一结点的下一结点,时间复杂度为O(1) :
JAVA代码实现
/**
* Definition for singly-linked list.
* public class ListNode
* int val;
* ListNode next;
* ListNode(int x) val = x;
*
*/
class Solution
public void deleteNode(ListNode node)
ListNode element = node.next;
node.next = element.next;
node.val = element.val;
注意:
如果要删除的结点是尾结点,我们需要遍历整个单链表,将尾结点的前一个结点的next指向null;
public ListNode deleteNode(ListNode head, ListNode tobeDelete)
if (head == null || tobeDelete == null)
return head;
if (tobeDelete.next != null)
// 要删除的节点不是尾节点
tobeDelete.val = tobeDelete.next.val;
tobeDelete.next = tobeDelete.next.next;
else
if (head == tobeDelete)
// 要删除的是头节点
head = head.next;
else
//要删除的是尾结点
ListNode cur = head;
// 找到尾结点的前一个结点
while (cur.next != tobeDelete)
cur = cur.next;
cur.next = null;
return head;
剑指offer18:删除链表的节点
注意:此处给出的是结点的值,而不是某个结点
解题方法:
由于头节点也是有可能被删除的,所以应该建立一个虚拟头节点dummy用于辅助删除头节点的操作,同时用双指针方法的话,设立dummy可以将操作统一。
- 设立虚拟头结点:dummy;
- current 用于记录当前要删除的结点;
- previous用于记录当前要删除结点的前一个结点;
- current.val = val 时,即current为当前要删除的结点,此时让current的前一个结点previous.next = current.next,即实现删除current结点
- 设置虚拟头结点dummy,即使要删除的是头结点,也可用上述代码,不会出现头结点没有previous的情况,设立虚拟头结点可以统一操作。
JAVA代码实现
/**
* Definition for singly-linked list.
* public class ListNode
* int val;
* ListNode next;
* ListNode(int x) val = x;
*
*/
class Solution
public ListNode deleteNode(ListNode head, int val)
if(head == null)
return null;
// 建立虚拟头结点
ListNode dummy = new ListNode(0);
// 指明dummy.next为头结点
dummy.next = head;
// previous用于记录 删除结点的前一结点,从而改变previous.next指向,删除current结点
ListNode previous = dummy;
// current用于记录 当前要删除的结点,删除该结点时只需让previous.next = current.next;
ListNode current = head;
while(current != null)
if(current.val == val)
// 当前结点是要删除的结点
previous.next = current.next;
// 已经删除结点后,需要跳出循环;
break;
// 如果current不是当前要删除的结点,继续往下遍历单链表
previous = previous.next;
current = current.next;
// 最后返回头结点
// 因为可能删除的是头结点,所以头结点 不能用head表示,但是虚拟头结点是不变的,dummy.next即为头结点
return dummy.next;
AcWing27:删除链表中重复的节点
解决方法
由于头结点也可能是重复的会被删除,所以建立虚拟结点dummy,使得操作统一;
要把当前为某个值的前一结点previous记录下来,和后面值比当前结点的值大的结点相连。
-
设立虚拟头结点:dummy
- current 用于记录第一个不等于previous.next的结点;
- previous用于记录当前结点的前一个结点;
-
while(current != null && previous.next.val == current.val) current = current.next; 使current指向第一个值不为previous.next的结点
-
if(previous.next.next == current) previous = previous.next;
说明current只跨越了一个结点,即previous.next.next=current 和previous.next的值不相同,即该段不重复,无需删除; -
else : current跨越了多个结点,目前current指向了第一个不等于previous.next.val的结点,只需让previous.next = current既可;
JAVA代码实现
传入参数ListNode head,int val
/**
* Definition for singly-linked list.
* public class ListNode
* int val;
* ListNode next;
* ListNode(int x) val = x;
*
*/
class Solution
public ListNode deleteNode(ListNode head,int val)
if(head == null || head.next == null)
return head;
// 创建虚拟头结点dummy
ListNode dummy = new ListNode(0);
dummy.next = head;
// previous用于记录当前比较值的前一个结点,用于改变previous.next指向
ListNode previous = dummy;
// 因为要比较current.val 和 previous.next.val,所以要先判断一下previous.next是否为空
while(previous != null && previous.next != null)
ListNode current = previous.next;
// 使current指向第一个值不等于previous.next.val的结点
while(current != null && current.val == previous.next.val)
current = current.next;
// 然后判断current跨越的是一个结点还是多个结点,判断是否有重复的值
if(previous.next.next == current)
// current = previous.next.next 的值和 previous.next的值不一样,即该段没有重复的值,无需删除
previous = previous.next;
else
// current跨越了多个值,让previous.next直接等于current既可
previous.next = current;
// 头结点可能会被删除,此时head无法准确表示头结点,dummy是不变的,dummy.next即为头结点
return dummy.next;
传入参数ListNode head
/**
* Definition for singly-linked list.
* public class ListNode
* int val;
* ListNode next;
* ListNode(int x) val = x;
*
*/
class Solution
public ListNode deleteDuplication(ListNode head)
if(head == null || head.next == null)
return null;
// 创建虚拟头结点,统一操作
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode previous = dummy;
while(previous != null && previous.next != null)
// current记录当前结点
ListNode current = previous.next;
while(current != null && previous.next.val == current.val)
// current为第一个val不等于previous.next.val的结点
current = current.next;
if(previous.next.next == current)
// current只跨越了一个结点,previous.next 和 previous.next.next 的值不同,即没有重复的值
previous = previous.next;
else
// 有重复的值
previous.next = current;
return dummy.next;
LetCode83:删除排序链表中的重复元素
解题方法
链表中的元素已经是排序的,故从头至尾遍历即可。
后一个元素和前一个元素相同则删除,这里的head肯定是不需要删除的,故不需要建立虚拟头节点dummy。
JAVA代码实现
/**
* Definition for singly-linked list.
* public class ListNode
* int val;
* ListNode next;
* ListNode(int x) val = x;
*
*/
class Solution
public ListNode deleteDuplicates(ListNode head)
if(head == null || head.next == null)
return null;
// current记录遍历单链表时当前的元素
ListNode current = head;
while(current != null && current.next != null)
if(current.val == current.next.val)
// 后面的值和当前值一样,说明元素重复,需要删除
current.next = current.next.next.next;
else
// 没有相同的元素,继续遍历单链表
current = current.next;
return head;
小白一个,可能有很多地方还讲解不到位,还请小伙伴们能够指出,也欢迎大佬指教!加油!努力工作!
以上是关于删除链表中的结点类型题JAVA解答的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode每日一题2020.6.26 面试题 02.01. 移除重复节点