您的位置:首页 > 职场人生

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

2017-11-16 22:08 796 查看
题目:在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: