剑指Offer总结第二部分

面试题16:数值的整数次方
题目:实现函数double power(double base,int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。实现C库函数中的Pow函数。

bool g_InvalidInput=false;
double power(double base,int exponent)
{
	g_InvalidInput=false;
	if(equal(base,0.0)&&exponent<0)
	{
		g_InvalidInput=true;
		return 0.0;
	}
	unsigned int absExponent=(unsigned int)(exponent);
	if(exponent<0)
	{
		absExponent=(unsigned int)(-exponent);
	}
	double result=PowerWithUnsignedExponent(base,absExponent);
	if(exponent<0)//取倒数
	{
		result=1.0/result;
	}
	return result;
}
double PowerWithUnsignedExponent(base,absExponent)
{
	double result=1.0;
	for(int i=1;i<=absExponent;i++)
	{
		result*=base;
	}
	return result;
]

如果exponent的次数过大,则for循环的计算量也比较大,则可以进行改进

double PowerWithUnsignedExponent(double base,unsigned int absExponent)
{
	if(absExponent==0)
	{
		return 1;
	}
	if(absExponent==1)
	{
		return base;
	}
	double result=PowerWithUnsignedExponent(base,absExponent>>1);
	resutl*=result;
	if(exponent&1==1)//if(exponent%2==1)位运算符比较快 二进制数字最后一位是1就是奇数,否则就是偶数
	{
		result*=base;
	}
	return result;
]

面试题17:打印从1到最大的n位数
题目:输入数字m,按顺序打印出从1到最大的n位十进制数。比如输入3,打印1、2、3,一直到最大的3位数999.

void PrintMaxOfNDigits(int n)
{
	int numbers=1;
	int i=0;
	while(i<n)//while(i++<n)
	{
		numbers*=10;
		i++;
	}
	for(i=1;i<numbers;++i)
	{
		printf("%d\t",i);
	}
}

但是没有考虑到n的范围,如果是大数会超出int的范围,我们可以使用unsigned int或者long long类型。因此我们可以用字符串或者数组表示大数。因为数字最大是n位,因此我们需要一个长度为n+1的字符串,字符串最后一位是结束符‘/0’,当实际数字不够n位的时候,在字符串的前半部分补0.我们需要做两件事:一是在字符串表达的数字上模拟加法;二是把字符串表达的数字打印出来。

void PrintToMaxOfDigits(int n)
{
	if(n<=0)
	{
		return;
	}
	char *number=new char[n+1];
	menset(number,'0',n);
	number[n]='\0';
	while(!Increment(number))//字符串模拟加法
	{
		PrintNumber(number);//打印数字
	}
	delete[]number;
}
bool Increment(char*number)
{
	bool isOverflow=false;
	int nTakeOver=0//进位
	int nLength=strlen(number);
	for(int i=nLength-1;i>=0;i--)
	{
		int nSum=number[i]-'0'+nTakeOver;
		if(i==nLength-1)
		{
			nSum++;
		}
		if(nSum>=10)//产生进位
		{
			if(i==0)
			{
				isOverflow=true;
			}
			else
			{
				nSum-=10;
				nTakeOver=1;
				number[i]=nSum+'0';
			}

		}
		else
		{
			number[i]=nSum+'0';
			break;//不进位直接退出,只加一
		}
	}
}
void PrintNumber(char * number)
{
	bool isBeginning0=true;
	int n=strlen(number);
	for(int i=0;i<n;++i)
	{
		if(isBeginning0&&number[i]!='0')
		{
			isBeginning0=true;
		}
		if(!isBeginning0)
		{
			printf("%c",number[i])
		}
	}
	printf("\t");

}

第二种解法全排列,每一位都从0到9排列一边,排在前面的0不打印。

void PrintToMaxOfDigits(int n)
{
	if(n<=0)
	{
		return;
	}
	char*number=new char[n+1];
	number[n]='\0';
	for(int i=0;i<10;++i)
	{
		number[0]=i+'0';
		PrintToMaxOfNDigitsRecursively(number,n,0);
	}
	delete number;
}
void PrintToMaxOfNDigitsRecursively(char*number,int length,int index)
{
	if(index==length-1)
	{
		printNumber(number);
		return;
	}
	for(int i=0;i<10;++i)
	{
		number[index+1]=i;
		PrintToMaxOfNDigitsRecursively(number,length,index+1);//设置好下一位就递归
	}
}

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

struct ListNode
{
	int m_Value;
	ListNode *m_pNext;
};
void DeleteNode(ListNode**PListHead,ListNode*pToBeDeleted)
{
	if(!PListHead||!pToBeDeleted)
	{
		return;
	}
	if(pToBeDeleted->m_pNext!=nullptr)//要删除的不是尾节点
	{
		ListNode*pNode=pToBeDeleted->m_pNext;
		pToBeDeleted->m_Value=pNode->m_Value;
		pToBeDeleted->m_pNext=pNode->m_pNext;
		delete pNode;
		pNode=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 pToBeDeleted;
		pToBeDeleted=nullptr;
	}
}

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

void DeleteDuplication(ListNode**pHead)
{
	if(*pHead&&pHead)
	{
		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_nValue)
		{
			needDelete=true;
		}
		if(!needDelete)
		{
			pPreNode=pNode;
			pNode=pNext;
		}
		else
		{
			int value=pNode->m_nValue;
			ListNode*pToBeDel=pNode;
			while(pToBeDel->m_nValue==value&&pToBeDel!=nullptr)
			{
				pNext=pToBeDel->m_pNext;
				delete pToBeDel;
				pToBeDel=nullptr;
				pToBeDel=pNext;
			}
			if(pPreNode==nullptr)
			{
				*pHead=pNext;
			}
			else{
				pPreNode->m_pNext=pNext;
			}

			pNode=pNext;
		}
		
	}
}

面试题19:正则表达式匹配
题目:请实现一个函数用来匹配包含‘.’和‘’的正则表达式。模式中的字符‘.’表示任意一个字符,而‘’表示它前面的字符可以出现任意次(含0次)。
当模式中的第二个字符不是‘’。如果字符串中的第一个字符和模式中的第一个字符匹配,那么在字符串和模式上都后移动一个字符,然后匹配剩余的字符串和模式。如果字符串中的第一个字符和模式中的第一个字符不相匹配,返回false。
当模式中的第二个字符是‘
’。一种选择是在模式上向后移动两个字符。这相当于‘’和它前面的字符被忽略了,因为‘’可以匹配字符串中的0个字符。如果模式中的第一个字符和字符串中的第一个字符相匹配,则在字符串上向后移动一个字符,而在模式上有两种选择:可以在模式上向后移动两个字符,也可以保持模式不变

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(*str==*pattern||(*pattern=='.'&&*str!='\0'))
		{
			return matchCore( str+1,pattern+2)||matchCore(str,pattern+2)||matchCore(str+1,pattern);
		}
		else
		{
			//忽略‘*’
			return matchCore(str,pattern+2);
		}
	}
	if(*str==*pattern||(*pattern=='.'&&*str!='\0'))
	{
		return matchCore(str+1,pattern+1);
	}
	return false;
}

面试题20:表示数值的字符串
题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。

bool isNumberic(const char *str)
{
	if(str==nullptr)
	{
		return false;
	}
	//先把整数扫描完
	bool numberic=scanInteger(&str);
	if(*str=='.')
	{
		++str;
		numberic=scanUnsignedInteger(&str)||numberic;
		
	}
	if(*str=='e'||*str=='E')
	{
		++str;
		numberic=numberic&&scanInteger(&str);
		
	}
	//12e5.4不是小数,C部分不能有·其他字符‘.’
	return numberic&&*str=='\0';
}
bool scanInteger(const char**str)
{
	if(**str==+||**str==-)
	
	{
		++(**str);
	}
	return scanUnsignedInteger(str);
}
bool scanUnsignedInteger(const char**str)
{
	const char*before=*str;
	while(**str!='\0'&&**str>='0'&&**str<='9')
	{
		++(**str);
	}
	return *str>before;
	
}

面试题21:调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使其所有奇数位于数组的前半部分,所有偶数位于数组的后半部分

void ReorderOddEven(int*pData,unsigned int length)
{
	if(pData==nullptr||length==0)
	{
		return;
	}
	int *pBegin=pData;
	int *pEnd=pData+length-1;
	while(pBegin<pEnd)
	{
		while(pBegin<pEnd&&(*pBegin&0x1)!=0)
		{
			pBegin--;
		}
		while(pBegin<pEnd&&(*pBegin&0x1)!=0)
		{
			pEnd--;
		}
		if(pBegin<pEnd)
		{
			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&&(*pBegin&0x1)!=0)
		{
			pBegin--;
		}
		while(pBegin<pEnd&&(*pBegin&0x1)!=0)
		{
			pEnd--;
		}
		if(pBegin<pEnd)
		{
			temp=*pBegin;
			*pBegin=*pEnd;
			*pEnd=temp;
		}
	}
}
bool isEvent(int n)
{
	return (n&1==0);
}
void RecoderOddEven(int*pData,unsigned int length)
{
	Reorder(pData,length,isEvent);
}

面试题22:链表中倒数第K个节点
题目:输入一个链表,输出该链表第K个节点
假设整个链表有n个节点,那么倒数第K个节点就是从头结点开始的n+1-k个节点。从头结点往后走n-k+1步就可以了。
也就是说我们需要遍历链表两遍,第一个统计出链表中节点的个数,第二次就能够找到第K个节点。

ListNode*FindKthToTail(ListNode*pListHead,unsigned int k)
{
	if(pListHead=nullptr||k=0)
	{
		return nullptr;
	}
	ListNode*pAhead=pListHead;
	ListNode*pBehind=nullptr;
	for(int i=0;i<k-1;i++)
	{
		if(pAhead->m_pNext!=nullptr)
		{
				pAhead=pAhead->m_pNext;
		}
		else
		{
			return nullptr;
		}

	}
	pBehind=pListHead;
	while(pAhead->m_pNext!=nullptr)
	{
		pAhead=pAhead->m_pNext;
		pBehind=pBehind->m_pNext;
	}
	return pBehind;
}

面试题23:链表中环的入口节点
题目:如果一个链表中包含环,如何找出环的入口节点

ListNode*MeetingNode(ListNode*pHead)
{
	if(pHead==nullptr)
	{
		return nullptr;
	}
	ListNode*pSlow=pHead->m_pNext;
	if(pSlow==nullptr)
	{
		return nullptr;
	}
	ListNode*pFast=pSlow->m_pNext;
	while(pFast!=nullptr&&pSlow!=nullptr)
	{
		if(pFast==pSlow)
		{
			return pFast;
		}
		pSlow=pSlow->m_pNext;
		pFast=pFast->m_pNext;
		if(pFast==nullptr)
		{
			return nullptr;
		}
		pFast=pFast->m_pNext;
	}
	return nullptr;
}


ListNode*EntryNodeOfLoop(ListNode*pHead)
{
	ListNode*meetingNode=MeetingNode(pHead);
	if(meetingNode==nullptr)
	{
		return nullptr;
	}
	ListNode*pNode1=meetingNode;
	int nodesLoop=1;
	while(pNode->m_pNext!=meetingNode)
	{
		pNode1=pNode1->m_pNext;
		++nodesLoop;                                                                                                                                                                                                                                                                                 
	}
	pNode1=pHead;
	for(int i=0:i<nodesLoop;i++)
	{
		pNode1=pNode1->m_pNext;
	}
	ListNode*pNode2=pHead;
	while(pNode2!=pNode1)
	{
		pNode1=pNode1->m_pNext;
		pNode2=pNode2->m_pNext;
	}
	return pNode1;
}

面试题24:反转链表
题目:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

ListNode*ReverseList(ListNode*pHead)
{
	ListNode*pReverseHead=nullptr
	ListNode*pNode=pHead;
	ListNode*pPrev=nullptr;
	while(pNode!=nullptr)
	{
		ListNode*pNext=pNode->m_pNext;
		if(pNext==nullptr)
		{
			pReverseHead=pNode;
		}
		pNode->m_pNext=pPrev;
		pPrev=pNode;
		pNode=pNext;
	}
	return pReverseHead;
}

面试题25:合并两个排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序。

ListNode*Merge(ListNode*pHead1,ListNode*pHead2)
{
	if(pHead1==nullptr)
	{
		return pHead2; 
	}
	if(pHead2==nullptr)
	{
		return pHead1; 
	}
	ListNode*pMergeHead=nullptr;
	if(pHead1->m_nValue<pHead2->m_nValue)
	{
		pMergeHead=pHead1;
		pMergeHead->m_pNext=Merge(pHead1->m_pNext,pHead2);
	}
	else
	{
		pMergeHead=pHead2;
		pMergeHead->m_pNext=Merge(pHead1,pHead2->m_pNext);
	}
	return pMergeHead;
}

面试题26:树的子结构
题目:输入两颗二叉树A和B,判断B是不是A的子结构

bool DoesTree1HaveTree2(BinaryTree*pRoot1,BinaryTree*pRoot2)
{
	if(pRoot2==nullptr)
	{
		return true;
	}
	if(pRoot1==nullptr)
	{
		return false;
	}

	if(!equal(pRoot1->m_dbValue,pRoot2->m_dbValue))
	{
		return false;
	}
	return DoesTree1HaveTree2(pRoot1->m_pLeft,pRoot2->m_pLeft)&&DoesTree1HaveTree2(pRoot1->m_pRight,pRoot2->m_pRight);
}
bool equal(int num1,int num2)
{
	if((num1-num2)>-0.0000001&&(num1-num2<0.0000001))
	{
		return true;
	}
	else
	{
		return false;
	}
}
bool HasSubtree(BinaryTree*pRoot1,BinaryTree*pRoot2)
{
	bool result=false;
	if(pRoot2!=nullptr&&pRoot1==nullptr)
	{
		if(equal(pRoot1->m_dbValue,pRoot2->m_dbValue))
		{
			 result=DoesTree1HaveTree2(pRoot1,pRoot2);
		}
		if(!result)
		{
			result=DoesTree1HaveTree2(pRoot1->m_pLeft,pRoot2);
		}
		if(!result)
		{
			result=DoesTree1HaveTree2(pRoot1->m_pRight,pRoot2);
		}
		
	}
	return result;
}

面试题27:二叉树的镜像
题目:请完成一个函数,输入一颗二叉树,该函数输出的是它的镜像。

void MirrorRescurively(BinaryTreeNode*pNode)
{
	if(pNode==nullptr)
	{
		return;
	}
	if(pNode->m_pLeft==nullptr&&pNode->m_pRight==nullptr)
	{
		return;
	}
	BinaryTreeNode*pTemp=pNode->m_pLeft;
	pNode->m_pLeft=pNode->m_pRight;
	pNode->m_pRight=pTemp;
	if(pNode->m_pLeft)
	{
		 MirrorRescurively(pNode->m_pLeft);
	}
	if(pNode->m_pRight)
	{
		MirrorRescurively(pNode->m_pRight);
	}
}

面试题28:对称的二叉树
题目:请实现一个函数,用来判断一颗二叉树是不是对称的。如果一颗二叉树和它的镜像一样,那么是对称的

bool isSymmetrical(BinaryTreeNode*pRoot)
{
	return isSymmetrical(pRoot,pRoot);
}
bool isSymmetrical(BinaryTreeNode*pRoot1,BinaryTreeNode*pRoot2)
{
	if(pRoot1==nullptr&&pRoot2==nullptr)
	{
		return true;
	}
	if(pRoot1==nullptr||pRoot2==nullptr)
	{
		return false;
	}
	if(pRoot1->m_nValue!=pRoot2->m_nValue)
	{
		return false;
	}
	return isSymmetrical(pRoot1->m_nLeft,pRoot2->m_nRight)&&isSymmetrical(pRoot1->m_nRight,pRoot2->m_nLeft);
}

面试题29:顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字

void PrintMatrixClockWisely(int **numbers,int columns,int rows)
{
	if(numbers==nullptr||columns<=0||rows<=0)
	{
		return;
	}
	int start=0;
	while(colums>2*start&&rows>2*start)
	{
		PrintMatrixInCircle(numbers,columns,rows,start);
		start++;
	}
}
void PrintMatrixInCircle(int **numbers,int columns,int rows,int start)
{
	 int endX=columns-1-start;
	 int endY=rows-1-start;
	 for(int i=0;i<endX;i++)
	 {
	 	int number=numbers[start][i];
	 	printNumber(number);
	 }
	 if(endY>start)
	 {
	 	for(int i=start+1;i<endY;i++)
	 	{
	 		int number=numbers[i][endX];
	 		printNumber(number);
	 	}
	 }
	 if(endY>start&&endX>start)
	 {]
	 	for(int i=endX-1;i>start;i--)
	 	{
	 		int number=numbers[i][endY];
	 		printNumber(number);
	 	}
	 }
	 if(endX>start&&endY>start+1)
	 {
	 	for(int i=endY-1;i>start+1;i--)
	 		int number=numbers[i][start];
	 		printNumber(number);
	 }
	 
}
																																																																						

面试题30:包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够找到栈的最小元素的min函数。调用min、push及pop时间复杂度都是O(1).

template<typename T>void StackWithMin<T>::push(T &value)
{
	m_data.push(value);
	if(m_min.size()==0||value<m_data.top())
	{
		m_min.push(value);
	}
	else
	{
		m_min.push(m_data.top());
	}
}
template<typename T>void StackWithMin<T>::pop()
{
	assert(m_min.size()>0&&m_data.size()>0);
	m_daya.pop();
	m_min.popo();
}
template<typename T>constT& StackWithMin<T>::min()const
{
	assert(m_min.size()>0&&m_data.size()>0);
	return m_min.top();
}

面试题32:从上到下打印二叉树
题目一:不分行从上到下打印二叉树

void PrintFromToBottom(BinaryTreeNode*pTreeRoot)
{
	if(!pTreeRoot)
	{
		return;
	}
	std::deque<BinaryTreeNode*>dequeTreeNode;
	dequeTreeNode.push_back(pTreeRoot);
	while(dequeTreeNode.size())
	{
		BinaryTreeNode*pNode=dequeTreeNode.front();
		dequeTreeNode.pop_front();
		printf("%d",pNode->m_nValue);
		if(pNode->m_pLeft)
		{
			dequeTreeNode.push_back(pNode->m_pLeft);
		}
		if(pNode->m_pRight)
		{
			dequeTreeNode.push_back(pNode->m_pRight);
		}
	}
}

题目二:分行从上到下打印二叉树

void Print(BinaryTreeNode*pRoot)
{
	if(pRoot==nullptr)
	{
		return;
	}
	std::queue<BinaryTreeNode*>nodes;
	nodes.push(pRoot);
	int nextLevel=0;
	int toBePrinted=1;
	while(!nodes.empty())
	{
		BinaryTreeNode*pNode=nodes.front();
		printf("%d",pNode->m_nValue);
		if(pNode->m_pLeft!=nullptr)
		{
			nodes.push(pNode->m_pLeft);
			++nextlevel;
		}
		if(pNode->m_pRight!=nullptr)
		{
			nodes.push(pNode->m_pRight);
			++nextlevel;
		}
		nodes.pop();
		--toBePrint;
		if(toBePrint==0)
		{
			printf("\n");
			toBePrint=nextLevel;
			nextLevel=0;

		}
	}
}

题目三:之字形打印二叉树

void Print(BinaryTreeNode*pRoot)
{
	if(pRoot==nullptr)
	{
		return;
	}
	std::stack<BinaryTreeNode*>levels[2];
	int current=0;
	int next=1;
	levels[0].push(pRoot);
	while(!levels[current].empty()||levels[next].empty())
	{
		BinaryTreeNode*pNode=levels[current].top();
		levels[current].pop;
		printf("%d",pNode->m_nValue);
		
		if(current==0)
		{
			if(pNode->m_pLeft!=nullptr)
			{
				levels[next].push(pNode->m_pLeft);
				
			}
			if(pNode->m_pRight!=nullptr)
			{
				levels[next].push(pNode->m_pRight);
				
			}
			
		}
		else
		{
			if(pNode->m_pRight!=nullptr)
			{
				levels[next].push(pNode->m_pRight);
				
			}
			if(pNode->m_pLeft!=nullptr)
			{
				levels[next].push(pNode->m_pLeft);
				
			}
		}
		if(levels[current].empty())
		{
			printf("\n");
			curretn=1-current;
			next=1-next;
		}
	}
}

面试题33:二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是返回true,否则返回false。

bool VertfySquenceOfBST(int sequence[],int length)
{
	if(sequence==nullptr||length<=0)
	{
		return false;
	}
	int root=sequence[length-1];
	int i=0;
	for(;i<length-1;++i)
	{
		if(sequence[i]>root){
			break;
		}
	}
	int j=i;
	for(;j<length-1;j++)
	{
		if(sequence[j]<root)
		{
			break;
		}
	}
	bool left=true;
	if(i>0)
	{
		left=VertfySquenceOfBST(sequence,i);
	}
	int right=true;
	if(j<length-1)
	{
		right=VertfySquenceOfBST(sequence+i,length-1-i);
	}
	return (left&&right);
}

面试题34:二叉树中和为某一值的路径
题目:输入一颗二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

void FindPath(BinaryTreeNode*pRoot,int expectedSum)
{
	if(pRoot==nullptr)
	{
		return;
	}
	std::vector<int>path;
	int currentSum=0;
	FindPath(pRoot,expectedSum,path,currentSum);
}
void FindPath(BinaryTreeNode*pRoot,int expectedSum,std::vector<int>&path,int currentSum){
	currentSum+=pRoot->m_nValue;
	path.push_back(pRoot->m_nValue);
	bool isLeaf=pRoot->m_pLeft==nullptr&&pRoot-<m_pRight==nullptr;
	if(currentSum==expectedSum&&isLeaf)
	{
		printf("A path is found:");
		std:vector<int>::iterator iter=path.begin();
		for(;iter<path.end();++iter)
		{
			printf("%d\t",*iter);
		}
		print("\n");
	}
	//如果不是叶节点,则遍历他的子节点
	if(pRoot->m_pLeft!=nullptr)
	{
		FindPath(pRoot->m_pLeft,expectedSum,path,currentSum);
	}
	if(pRoot-<m_pRight!=nullptr)
	{
		FindPath(pRoot-<m_pRight,expectedSum,path,currentSum);
	}
	paht.pop_back();
}

面试题35:复杂链表的复制
题目:请实现函数ComplexListNodeClone(ComplexListNodepHead),复制一个复杂链表。在复杂链表中,每个节点除了有一个m_pNext指针指向下一个节点,还有一个m_pSibling指针指向链表中的任意节点或者nullptr。

void CloneNodes(ComplexListNode*pHead)
{
	ComplexListNode*pNode=pHead;
	while(pNode!=nullptr)
	{
		ComplexListNode*pClone=new ComplexListNode();
		pClone->m_nValue=pNode->m_nValue;
		pClone->m_pNext=pNode->m_pNext;
		pClone->m_pSibling=nullptr;
		pNode->m_pNext=pClone;
		pNode=pClone->m_pNext;
	}
}
void ConnectSiblingNodes(ComplexListNode*pHead)
{
	ComplexListNode*pNode=pHead;
	while(pNode!=nullptr)
	{
		ComplexListNode*pClone=pNode->m_pNext;
		if(pNode->m_pSibling!=nullptr)
		{
			pClone->m_pSibling=pNode->m_pNext->m_pSibling;
			
		}
		pNode=pClone->m_pNext;
	}
}
ComplexListNode*ReconnectNodes(ComplexListNode*pHead)
{
	ComplexListNode*pNode=pHead;
	ComplexListNode*pCloneHead=nullptr;
	ComplexListNode*pCloneNode=nullptr;
	if(pNode!=nullptr)
	{
		pCloneHead=pCloneNode=pNode->m_pNext;
		pNode->m_pNext=pCloneNode->m_pNext;
		pNode=pCloneNode->m_pNext;
	}
	while(pNode!=nullptr)
	{
		pClone->m_pNext=pNode->m_pNext;
		pClone=pClone->m_pNext;
		pNode->m_pNext=pClone->m_pNext;
		pNode=pNode->m_pNext;
	}
}
ComplexListNode*Clone(ComplexListNode*pHead)
{
	CloneNodes(pHead);
	ConnectSiblingNodes(pHead);
	return ReconnectNodes(pHead);
}

面试题36:二叉搜索树与双向链表
题目:输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。

BinaryTreeNode*Convert(BinaryTreeNode*pRootOfTree)
{
	BinaryTreeNode*pLastNodeInList==nullptr;
	ConvertNode(pRootOfTree,&pLastNodeInList);
	BinaryTreeNode*pHeadOfList=pLastNodeInList;
	while(pHeadOfList!=nullptr&&pHeadOfList->m_pLeft!=nullptr)
	{
		pHeadOfList=pHeadOfList->m_pList;
	}
	return pHeadOfList;
}
void ConvertNode(BinaryTreeNode*pNode,BinaryTreeNode**pLastNodeInList)
{
	if(pNode==nullptr)
	{
		return;
	}
	BinaryTreeNode*pCurrent=pNode;
	if(pCurrent->m_pLeft!=nullptr)
	{
		ConvertNode(pCurrent->m_pLeft,pLastNodeInList);
	}
	pCurrent->m_pLeft=*pLastNodeInList;
	if(*pLastNodeInList!=nullptr)
	{
		(*pLastNodeInList)->m_pRight=pCurrent;
	}
	*pLastNodeInList=pCurrent;
	if(pCurrent->m_pRight!=nullptr)
	{
		ConvertNode(pCurrent->m_pRight,pLastNodeInList);
	}
}

面试题37:序列化二叉树
题目:请实现一个函数,分别用来序列化和反序列化二叉树

void Serialize(BinaryTreeNode*pRoot,string&str)
{
	if(pRoot==nullptr)
	{
		str+="#";		
		return;
	}
	string temp=std::to_string(pRoot->m_pValue);
	str+=temp;
	str+=',';
	
	Serialize(pRoot->m_pLeft,str);
	Serialize(pRoot->m_pRight,str);
}
char* Serialize(TreeNode *root) {    
        if(!root){
            return NULL;
        }
        string str;
        SerializeCore(root, str);
        // 把str流中转换为字符串返回
        int length = str.length();
        char* res = new char[length+1];
        // 把str流中转换为字符串返回
        for(int i = 0; i < length; i++){
            res[i] = str[i];
        }
        res[length] = '\0';
        return res;
}
TreeNode* Deserialize(char *str) {
    if(!str){
       return NULL;
    }
    TreeNode* res = DeserializeCore(&str);
    return res;
}
    TreeNode* DeserializeCore(char** str){
        // 到达叶节点时,调用两次,都返回null,所以构建完毕,返回父节点的构建
        if(**str == '#'){
            (*str)++;
            return NULL;
        }
        // 因为整数是用字符串表示,一个字符表示一位,先进行转换
        int num = 0;
        while(**str != ',' && **str != '\0'){
            num = num * 10 + ((**str) - '0');
            (*str)++;
        }
        TreeNode* root = new TreeNode(num);
        if(**str == '\0'){
            return root;
        }
        else{
            (*str)++;
        }
        root->left = DeserializeCore(str);
        root->right = DeserializeCore(str);
        return root;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值