剑指offer刷题【12】

面试题18:删除链表的节点

在O(1)时间内删除链表节点。

给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。

struct ListNode
{
	int m_nValue;
	ListNode* m_pNext;
}

void DeleteNode(List** pListHead, ListNode* pToBeDeleted);

常规的做法无疑是从链表的头节点开始,顺序遍历查找要删除的节点,并在链表中删除。

在单向链表中,节点中没有指向抢一个节点的指针,所以只好从链表的头节点开始顺序查找。

如果我们把下一个

void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted)
{
	if(!pListHead ||!pToBeDeleted)
		return;
	//要删除的节点不是尾节点
	if(pToBeDelete->m_pNext!=nullptr)
	{
		ListNode* pNext = pToBeDelete->m_pNext;
		pToBeDeleted->m_nValue = pNext->m_nValue;
		pToBeDeleted->m_pNext = pNext->m_pNext;

		delete pNext;
		pNext = nullptr;
	}
}


//链表只有一个节点,删除头节点(也是尾节点)
	else if(*pListHead == pToBeDeleted)
	{
		delete pToBeDeleted;
		pToBeDeleted = nullptr;
		*pListHead = nullptr;
	}

else
{
	ListNode* pNode = *pListHead;
	while(pNode->m_pNext != pToBeDeleted)
	{
		pNode = pNode->m_pNext;
	}
	
	pNode->m_pNext = nullptr;
	delete pToBeDelete;
	pToBeDelete = nullptr;
}
}

把节点j的内容复制覆盖节点i,接下来再把节点i的m_pNext指向j的下一个节点,在删除节点j。

删除链表中重复的节点

在一个排序的链表中,如何删除重复节点?

确定删除函数的参数,输入需要带删除链表的头节点,头节点可能与后面的节点重复,也就是说头节点也有可能被删除,因此删除函数应该声明为void deleteDuplication(ListNode** pHead)

void DeleteDuplication(ListNode** pHead)
{
	if(pHead == nullptr ||*pHead == nullptr)
		return;
	
	ListNode* pPreNode = nullptr;
	ListNode* pNode = *pHead;

	while(pNode != nullptr)
	{
		ListNode* pNext = pNode->m_pNext;
		bool needDelete = false;
		if(pNext!=nullptr&&pNext->m_nValue==pNode->m_nVaule)
			needDelete = true;

		if(!needDelete)
		{
			pPreNode = pNode;
			pNode = pNode->m_pNext;
		}
		else
		{
			int value = pNode->m_nValue;
			ListNode* pToBeDel = pNode;
			while(pToBeDel != nullptr && pToBeDel->m_nValue == value)
			{	
				pNext = pToBeDel->m_pNext;
				
				delete pToBeDel;
				pToBeDel = nullptr;

				pToBeDel = pNext;
			}

			if(pPreNode == nullptr)
				*pHead = pNext;
			else
				pPreNode -> m_pNext=pNext;
			pNode=pNext;
		}
	}
}

面试题19:正则表达式匹配

请实现一个函数用来匹配包含’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次。

bool match(char* str,char* pattern)
{
	if(str == nullptr||pattern == nullptr)
		return false;
	
	return matchCore(str,pattern);
	
}


bool matchCore(char* str,char* pattern)
{
	if(*str == '\0'&&*pattern == '\0')
		return true;
	
	if(*str != '\0'&&*pattern =='\0')
		return false;

	if(*(pattern+1) =='*')
	{
		if(*pattern==*str||(*pattern == '.'&& *str!='\0'))
			return matchCore(str+1,str+2)
			||matchCore(str+1,pattern)
			||matchCore(str,pattern+2);
		
		else
			return matchCore(str,pattern+2);
		
	if(*str == *pattern||(*pattern == '.'&&*str!= '\0'))
		return matchCore(str+1,pattern+1);

	return false;
	}
}

请实现一个函数用来判断字符串是否表示数值(包含整数和小数)

bool isNumeric(const char* str)
{
	if(str == nullptr)
		return false;
	bool numeric = scanInteger(&str);

	if(*str =='!')
	{
		++str;

		numeric = scanUnsignedInteger(&str)||number;
	}
		if(*str == 'e'||*str == 'E')
		{
			++str;
			numeric = numeric&&scanInteger(&str);
			
		}
	return numeric && *str =='\0';
	
}
bool scanUnsignedInteger(const char** str)
{
	const char* before = *str;
	while(** str!='\0'&& **str>='0'&&**str<='9')
		++(*str);
	return *str>before;
}


bool scanInteger(const char**  str)
{
	if(**str == '+'||**str =='-')
		++(*str);
	return scanUnsignedInteger(str);
}

全面考虑数值整数、小数、指数部分的特点

调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

双指针 :第一个指针初始化时指向数组的第一个数字,它只想后移动,第二个指针初始化时指向数组的最后一个数字,它只向前移动。

void ReorderOddEven(int *pData,unsigned int length)
{
	if(pData == nullptr||length ==0)
		return ;
	int*pBegin = pData;
	int*pEnd = pData+length-1;

	while(pBegin<pEnd)
	{
		//向后移动pBegin,直到它指向偶数
		while(pBegin<pEnd&&(*pBegin & 0x1)!=0)
			pBegin++;
		
		while(pBegin<pEnd && (*pEnd &0x1)==0)
			pEnd--;

		if(pBegin<pEnd)
		{
			int temp = *pBegin;
			*pBegin = *pEnd;
			*pEnd = temp;
		}
	}
}

考虑可扩展的解法

void Reorder(int *pData,unsigned int length ,bool(*func)(int))
{
	if(pData == nullptr||length ==0)
		return;
	int *pBegin = pData;
	int *pEnd = pData+length-1;

	while(pBegin<pEnd)
	{
		while(pBegin<pEnd && !func(*pBegin))
			pBegin++;
		while(pBegin < pEnd&&func(*pEnd))
			pEnd--;
		
		if(pBegin<pEnd)
		{
			int temp = *pBegin;
			 *pBegin = *pEnd;
			 *pEnd = temp;
			
		}
		
	}
}

bool isEven(int n)
{
	return (n&1)==0;


}

void ReorderOddEven(int *pData,unsigned int length)
{
	Reorder(pData,length,isEven);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杠杠的丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值