给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
函数的声明如下:
void DeleteNode(ListNode pListHead, ListNode pToBeDeleted)
一般单链表删除某个节点,需要知道删除节点的前一个节点,则需要O(n)的遍历时间,显然常规思路是不行的。在仔细看题目,换一种思路,既然不能在O(1)得到删除节点的前一个元素,但我们可以轻松得到后一个元素,这样,我们何不把后一个元素赋值给待删除节点,这样也就相当于是删除了当前元素。可见,该方法可行,但如果待删除节点为最后一个节点,则不能按照以上思路,没有办法,只能按照常规方法遍历,时间复杂度为O(n),是不是不符合题目要求呢?可能很多人在这就会怀疑自己的思考,从而放弃这种思路,最后可能放弃这道题,这就是这道面试题有意思的地方,虽看简单,但是考察了大家的分析判断能力,是否拥有强大的心理,充分自信。其实我们分析一下,仍然是满足题目要求的,如果删除节点为前面的n-1个节点,则时间复杂度为O(1),只有删除节点为最后一个时,时间复杂度才为O(n),所以平均的时间复杂度为:(O(1) * (n-1) + O(n))/n = O(1);仍然为O(1).下面见代码:
/* Delete a node in a list with O(1)
* input: pListHead - the head of list
* pToBeDeleted - the node to be deleted
*/
void DeleteNode(ListNode pListHead, ListNode pToBeDeleted)
{
if (pListHead == null || pToBeDeleted == null)
return;
if (pToBeDeleted.next != null) {
ListNode pNext = pToBeDeleted.next;
pToBeDeleted.next = pNext.next;
pToBeDeleted.val= pNext.val;
}
else { //待删除节点为尾节点
ListNode pTemp = pListHead;
while(pTemp.next != pToBeDeleted)
pTemp = pTemp.next;
pTemp.next = null;
}
}