题目1:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。
思路:最简单的一种想法是从链表的头结点开始遍历,找到要删除节点的前一个节点。但是这种方法的时间复杂度是O(n),不符合题目的要求。其实我们可以不需要找到删除节点的前一个指针,只需要将删除节点i后面一个节点j的值和它的下一个节点信息赋给要删除的节点i,再删除节点j就可以了。对于在链表中间的节点来说,时间复杂度是O(1),对于最后一个节点,仍然要从头结点开始遍历,时间复杂度是O(n),这样一来总的时间复杂度仍然是O(1),符合题目要求。
代码:
public void deleteNode(ListNode head, ListNode deListNode) {
if (deListNode == null || head == null)
return;
if (head == deListNode) {
head = null;
} else {
// 若删除节点是末尾节点,往后移一个
if (deListNode.nextNode == null) {
ListNode pointListNode = head; //如果要删除的节点就是头结点的话,是不是就会直接到这一步?那么头结点之后的节点是不是就没有了呢?
while (pointListNode.nextNode.nextNode != null) {
pointListNode = pointListNode.nextNode;
}
pointListNode.nextNode = null;
} else {
deListNode.data = deListNode.nextNode.data;
deListNode.nextNode = deListNode.nextNode.nextNode;
}
}
}
题目2:删除链表中的重复节点
在一个排序链表中,如何删除重复的节点。
思路:注意在上面的题中已经说明是排序链表,也就是说重复的元素一定是排在一起的,这是一个前提。我们从头到尾遍历整个链表,如果当前节点的值与下一个节点的值相同,那么它们就是重复节点,都可以被删除。为了保证删除后的链表仍然是相连的,我们要把当前节点的前一个节点和后面值比前面大的节点相连。对于链表的部分要注意细节,很容易写错。代码原文链接如下:https://blog.youkuaiyun.com/zjkC050818/article/details/72897164
代码:
public ListNode deleteDuplication_3(ListNode pHead) {
if(pHead==null||pHead.next==null)
return pHead;
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; //一个辅助节点用来找到不是重复节点的下一个节点,结果放在pNext中
while(pToBeDel!=null&&pToBeDel.val==value){
pNext=pToBeDel.next;
pToBeDel=pNext;
}
if(pPreNode==null) //这种情况针对的是头结点重复的情况
pHead=pNext;
else
pPreNode.next=pNext;
pNode=pNext; //继续往下查找重复节点
}
}
return pHead; //最后返回头结点
}