第18题:在O(1)时间删除链表结点+删除链表中重复的节点

题目描述:题目描述在O(1)时间删除链表结点
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。

 

考查创新编程能力。

 

思路:

1.如果从头到尾遍历,时间O(n)

2.如果将待删除节点的下一个节点j复制到待删除节点i上,然后将i的下一个节点指向j的下一个节点,删除j的节点。

3.对于尾节点,需要从头开始遍历

4.对于只有一个节点的链表,要将*HeadNode设置为Nullptr.

5.时间复杂度

n-1个非尾节点,时间O(1)

1个尾节点,时间O(n)

最终((n-1)*O(1)+O(n))/n=O(1)符合题目要求

 

 

注意:

1.每次删除完节点后,要释放节点,即将节点的指针设为nullptr。

2.n-1个非尾节点,删除的是待删除节点的下一个pNext,而不是本身的节点。

3.最后一个尾节点,用while遍历,pNode指针向后指,找到最后一个节点,删除后,将pNode->Next设为nullptr。

//已知该节点存在链表中
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
	//1.如果链表头节点或待删除节点为空,返回
	if (!pListHead || !pToBeDeleted)
		return;
	//2.多个节点的链表,前n-1个非尾节点
	if (pToBeDeleted->m_pNext)
	{
		//2.1 pNext:待删除节点J的下个节点K
		ListNode* pNext = pToBeDeleted->m_pNext;
		//2.2 复制值J=K
		pToBeDeleted->m_nValue = pNext->m_nValue;
		//2.3 复制指针J->NEXT=K->NEXT
		pToBeDeleted->m_pNext = pNext->m_pNext;

		//2.4 删去下个节点K(pNext)
		delete pNext;

		//2.5 pNext设为空指针
		pNext = nullptr;

	}

	//3.只有一个节点的链表,删完要将头节点指针设为空
	else if(*pListHead==pToBeDeleted)
	{
		//3.1删除节点
		delete pToBeDeleted; 

		//3.2 释放删除节点的指针
		pToBeDeleted = nullptr;

		//3.3 删除后将头节点设为空指针
		*pListHead = nullptr;

	}
	//4.如果是最后一个尾节点,就用遍历
	else
	{
		//4.1 pNode:遍历指针,从头开始
		ListNode* pNode = *pListHead;
		//4.2 while遍历找到pNode的下一个节点是要删除的节点
		while(pNode->m_pNext == pToBeDeleted)
		{ 
			//4.2.1 指针向后指
			pNode = pNode->m_pNext; 
		}
		//4.3 将pNode的下一个节点设为空
		pNode->m_pNext = nullptr;

		//4.4 删除最后的节点
		delete pToBeDeleted;
		//4.5 释放指针 
		pToBeDeleted = nullptr; 

	}


}

 

题目描述

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

 

思路:

1.确定函数的参数,头节点也可能被删除,所以函数声明应该为

void deleteDuplication(ListNode** pHead);

2.从头到尾遍历链表,确保pPreNode始终和下一个没有重复的节点连在一起。

 

//函数的参数:ListNode** pHead。
//因为头节点可能重复,会被删除,所以不用ListNode* pHead
void DeleteDuplication(ListNode** pHead) 
{
	//1.如果是空链表或头节点为空,返回 
	if (!pHead || !*pHead) 
		return;
	 
	//2.ListNode* pNode:初始化指向当前头节点*pHead
	ListNode* pNode = *pHead;
	 
	//3.ListNode* pPreNode:指向上个节点,初始化为空
	ListNode* pPreNode = nullptr;

	//4.循环遍历
	while (pNode)
	{
		//4.1.新建一个节点pNext,指向下个节点
		ListNode* pNext = pNode->m_pNext;

		//4.2 设置标记:pNode节点是否需要删除
		bool needDetele = false;

		//4.3 如果下个节点pNext不为空,且pNode节点值和下个节点pNext的值相同,pNode节点就需要删除
		if (pNext!=nullptr && pNext->m_nValue == pNode->m_nValue)
			needDetele = true;
		   

		//4.4 如果不需要删除,就遍历下一个
		if (!needDetele)
		{
			//4.4.1 上个节点pPreNode设为当前节点pNode 
			pPreNode = pNode;

			//4.4.2 当前节点pNode设为下个节点pNext
			pNode = pNext;

		/*	pNode->m_nValue = pNext->m_nValue;
			pNode->m_pNext = pNext->m_pNext;*/
		}
 
		//4.5 否则,开始删除
		else
		{
			//4.5.1 记录pNode值
			int value = pNode->m_nValue;

			//4.5.2 定义要删除的节点变量toBeDeleted,初始化为该节点
			ListNode* toBeDeleted = pNode; 
	 
			//4.5.3 循环遍历:如果toBeDeleted节点不为空,且等于下一个节点,就将toBeDeleted删除,
			while (toBeDeleted&&value == toBeDeleted->m_nValue)
			{
				//4.5.3.1 pNext指向toBeDeleted下个节点
				pNext = toBeDeleted->m_pNext;

				//4.5.3.2 删除toBeDeleted节点
				delete toBeDeleted;
				toBeDeleted = nullptr;

				//4.5.3.3 toBeDeleted节点赋值为下个节点pNext
				toBeDeleted = pNext; 
			} 

			//4.5.4 如果删除的是头节点,即pPreNode为空,将头节点改为下个节点
			if (!pPreNode)
				*pHead = pNext;
			//4.5.5 否则,将pPreNode的下个节点设置为下个节点pNext
			else
				pPreNode->m_pNext = pNext;

			//4.5.6 当前节点pNode设为下个节点pNext
			pNode = pNext;
		}	
	}
}

第二遍

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        //1.如果链表为空或者头节点为空,返回nullptr
        if(!pHead)
            return nullptr;
        
        //2.pPreNode指向上一个节点,初始化为nullptr;
        ListNode* pPreNode = nullptr;
        
        //3.当前节点pNode,初始化指向头节点
        ListNode* pNode=pHead;
        
        //4.删除重复节点,while循环条件:pNode不为空
        while(pNode)
        {
            //4.1 pNext指向pNode下个节点
            ListNode* pNext= pNode->next;
            
            //4.2 bool标记pNode是否需要删除,默认值false
            bool needDelete=false;
            
            //4.3 更新needDelete标记值:如果pNode的值和下个节点pNext的值相等的话,这个节点需要删除
            if(pNext&&pNode->val==pNext->val)
                needDelete=true;
            
            //4.4 如果不需要删除,当前节点pNode向后指一个pNext,上一个节点pPreNode指向当前节点
            if(!needDelete)
            {
                pPreNode=pNode;
                pNode=pNext;
            }
            //4.5 否则需要删除
            else
            {
                //4.5.1 存放当前pNode的值int
                int value=pNode->val;
                
                //4.5.2 定义待删除的节点toBeDeleted
                ListNode* toBeDeleted=pNode;
                
                //4.5.2 如果待删除的节点toBeDeleted存在,且值等于当前pNode的值,则删除该节点
                while(toBeDeleted&&toBeDeleted->val==value)
                {
                    //4.5.2.1 保存待删除节点的下个节点
                    pNext=toBeDeleted->next;
                    
                    //4.5.2.2 删除该节点
                    delete toBeDeleted;
                    toBeDeleted=nullptr;
                    
                    //4.5.2.3 重新更新待删除的节点
                    toBeDeleted=pNext;
                    
                }
                //4.5.3 如果上个节点为空,即头节点被删除,头节点为pNext
                if(!pPreNode)
                    pHead=pNext;
                //4.5.4上一个节点pPreNode指向当前节点
                else
                   pPreNode->next=pNext;
                
                //4.6 将当前节点pNode向后指一个pNext 
                pNode=pNext;
            }
        }
    //5. 返回链表
    return pHead;
    }
};

网友的

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if (pHead==NULL)
            return NULL;
        if (pHead!=NULL && pHead->next==NULL)
            return pHead;
                 
        ListNode* current;
         
        if ( pHead->next->val==pHead->val){
            current=pHead->next->next;
            while (current != NULL && current->val==pHead->val)
                current=current->next;
            return deleteDuplication(current);                     
        }
         
        else {
            current=pHead->next;
            pHead->next=deleteDuplication(current);
            return pHead;
        }    
    }
};

 

posted @ 2019-02-04 19:38  lightmare  阅读(234)  评论(0编辑  收藏  举报