删除链表中的结点类型题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解答的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer-代码的完整性面试题18.2:删除链表中的重复节点

面试题:删除链表中的重复节点

链表经典面试题(含图解)

剑指offer链表题的双指针法总结

剑指Offer面试题15(Java版):链表中倒数第K个结点

《剑指offer》:[57]删除链表中重复的结点