题目一:在O(1)时间内删除链表节点
链表定义:
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
思路:我们知道,常规删除链表节点需要从头开始遍历,需要O(n)的时间。那么要如何才能实现O(1)删除节点呢?
很简单,假设待删除节点为pToBeDeleted,我们可以直接取得它的下一个节点pNext,让pToBeDeleted.val=next.val,再pToBeDeleted.next=pNext.next,最后pNext=null,结果就是删除了pToBeDeleted。
有一个特殊情况,当pToBeDeleted是最后一个节点时,无法如此操作,所以我们要从头节点开始遍历到尾结点来删除它。
void Deleted(ListNode head,ListNode pToBeDeleted)
{
if (head==null || pToBeDeleted==null)
return;
//当被删除结点不是最后一个节点时
if (pToBeDeleted.next!=null)
{
pNext=pToBeDeleted.next;
pToBeDeleted.val=pNext.val;
pToBeDeleted.next=pNext.next;
pNext=null;
}
//当被删除结点是头节点时
else if (pToBeDeleted==head)
{
head==null;
}
//当被删除结点是最后一个节点时
else
{
ListNode tmp=head;
while (tmp.next!=pToBeDeleted)
{
tmp=tmp.next;
}
tmp.next=null;
pToBeDeledte=null;
}
}
进行时间复杂度分析:对于n-1个非尾节点而言,删除需要O(1),对于尾节点,删除需要O(n),所以平均时间复杂度是[(n-1)*O(1)+O(n)]/n=O(1)。
题目二:删除链表中重复的节点。在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
思路:很直观,就是遇到重复节点的时候删除,然后注意重复节点前面的节点要进行链接,代码如下:
public ListNode deleteDuplication(ListNode pHead)
{
if (pHead==null)
return null;
ListNode pPreNode=null;
ListNode pNode=pHead;
while (pNode != null)
{
ListNode pNext=pNode.next;
boolean needDelete=false;
if (pNext != null && pNext.val==pNode.val)
needDelete=true;
if (!needDelete)
{
pPreNode=pNode;
pNode=pNode.next;
}
else
{
int value=pNode.val;
ListNode pToBeDel=pNode;
/*删除重复的节点
while (pToBeDel!=null && pToBeDel.val==value)
{
pNext=pToBeDel.next;
pToBeDel=null;
pToBeDel=pNext;
}
*/
if (pPreNode == null)
pHead=pNext;
else
pPreNode.next=pNext;
pNode=pNext;
}
}
return pHead;
}