剑指Offer 面试题18:删除链表节点 Java代码实现

题目:在O(1)时间内删除链表节点。

给定单向链表头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。


这儿采用有头结点的单链表结构,头结点的存在是为了方便操作,针对单链表来说,如果带头结点的话,头指针指向头结点,头结点指向首结点;如果不带头结点的话,头指针指向首结点,如果进行插入和删除操作,必须要注意是否是在链表头进行,要分情况处理,而带头结点的不用分情况,比较方便。


一般情况下,删除单链表中的第k个节点,需要遍历链表找到对应节点的上一节点,然后删除第k个节点,这样的时间复杂度自然是O(n)。这儿情况比较特殊,方法参数给了我们需要删除的节点引用,就可以采用一种新的思路删除该节点。具体而言,就是把待删除节点的下一节点数据域复制到待删除节点,然后删除下一节点。整个过程实际上就是删除了待删除节点的内容,时间复杂度为O(1)。当然,尾节点没有下一节点,我们还是需要遍历,不过平均复杂度仍然是O(1)。

节点类代码如下,就是一个value域,一个next域。里面的函数是打印输出链表,方便看结果。

public class ListNode {
	int value;
	ListNode next;

	public static void printStr(ListNode head) {
		if (head == null)
			return;
		ListNode pNode = head.next;
		while (pNode != null) {
			if(pNode.next==null){
				System.out.print(pNode.value);
				System.out.println();
				pNode = pNode.next;
			}else{
				System.out.print(pNode.value);
				System.out.print("->");
				pNode = pNode.next;
			}
		}
	}
}

主要方法代码:

public static void deleteNode(ListNode pHead,ListNode toBeDelete){
		if(pHead==null||toBeDelete==null)
			return;
		
		//要删除的节点不是尾节点
		if(toBeDelete.next!=null){
			ListNode pNext=toBeDelete.next;
			toBeDelete.value=pNext.value;
			toBeDelete.next=pNext.next;
			
			pNext=null;
		}else if(pHead==toBeDelete){
			//链表只有一个节点
			pHead=null;
		}else{
			//链表有多个节点,要删除尾节点
			//只有这种情况下时间复杂度为O(n)
			ListNode pNode=pHead;
			while(pNode.next!=toBeDelete){
				pNode=pNode.next;
			}
			pNode.next=null;
			toBeDelete=null;
		}
	}

上面代码中必须要求我们输入的参数,节点toBeDelete必须在链表中。受限于O(1)的要求,这儿没有做检查。

测试代码如下:

public static void main(String[] args) {
		ListNode head = new ListNode();
		ListNode node1 = new ListNode();
		ListNode node2 = new ListNode();
		ListNode node3 = new ListNode();
		ListNode node4 = new ListNode();
		//采有头结点的链表,数据域不用,指针域指向第一个有数据的链表节点
		head.next = node1;
		node1.value = 1;
		node1.next = node2;
		node2.value = 2;
		node2.next = node3;
		node3.value = 3;
		node3.next = node4;
		node4.value=4;
		node4.next = null;
		ListNode.printStr(head);
//		deleteNode(head, node1);
//		deleteNode(head, node4);
		deleteNode(head, node2);
		ListNode.printStr(head);
	}
输出如下:

1->2->3->4
1->3->4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值