面试题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;
}
};