面试(六)(编程题)

题目来源剑指offer

(1)输入一个链表的头节点,从尾到头打印出每个节点的值:
链表节点定义:

struct ListNode
{
	int key;
	ListNode pNext;
};

思路:
可将链表的指针方过来,改变链表的方向就可以实现,但是这会改变链表的结构,需要询问考官是否可以。这给出两种不改变结构的方法
1、处理这种“后进先出”问题,可通过栈实现。每通过一个节点,将节点放入一个栈中。当遍历完整个链表后,从栈顶开始逐个输出节点值。

void list(Listnode* pHead)
{
	std::stack<ListNode*>nodes;
	ListNode* pNodde=pHead;
	while(pNode !=nullptr)
	{
		nodes.push(pNode);
		pNode=pNode->pNext
	}
	while(!nodes.empty())
	{
		pNode=nodes.top();
		printf("%d\t",pNode->m_nBValue);
		nodes.pop();
	}
}

2、通过递归,每到一个节点,递归输出后面的节点,再输出自身

void list2(ListNode* pHead)
{
	if(pHead!=nullptr)
	{
		if(pHead->m_pNext!=nullptr)
		{
			list2(pHead->m_pNext);
		}
		printf(%d\t",pHead->m_nBValue);
	}
}

(2)给出二叉树的前序遍历和中序遍历结果,重建二叉树。假设不存在重复数字,前序遍历结果{1,2,4,7,3,5,6,8}中序遍历结果(4,7,2,1,5,3,8,6}
二叉树节点定义:

struct BinaryTreeNode
{
	int m_nBValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
}

知识点:
在这里插入图片描述

  • 前序遍历:先访问根节点,再访问左子节点,最后访问右子节点,如图二叉树访问结果:1,2,4,5,3,6,7
  • 中序遍历:先访问左子节点,再访问根节点,最后访问右子节点,如图二叉树访问结果:4,2,5,1,6,3,7
  • 后续遍历:先访问左子节点,再访问右子节点最后,访问根节点,如图二叉树访问结果:4,5,2,6,7,3,1

思路:可依据结果还原二叉树:
在这里插入图片描述
前序遍历1就是根节点的值,中序遍历可知,4,7,2组成了左子树,5,3,8,6组成右子树,同样的方法可以知道每个数的位置
代码实现:

BinaryTreeNode* construct(int* preorder,int* inorder,int length)
{
	if(preorder==nullptr || inorder==nullptr || length<=0)
	{
		return nullptr;
	}
	return constructCore(preorder,preorder+length=1,inorder,inorder+length-1);
}

BinaryTreeNode* constructCore(int* startPreorder,int* endPreorder,int* startInorder,int* endInorder)
{
	//前序遍历第一个值是根节点的值
	int rootBValue=startPreorder[0];
	BinaryTreeNode* root=new BinaryTreeNode();
	root->m_nValue=rootValue;
	root->m_pLeft=root->m_pRight=nullptr;
	if(startpreorder==endPreorder)
	{
		if(startInorder==endInorder && *startPreorder==*startInorder)
		{
			return root;
		}
		else{
			throw std::exception("Invalid input");
		}
	}
	//在中序遍历找根节点的值
	int* rootInorder=startInorder;
	while(rootInorder<=endInorder && *rootInorder!=rootValue){
		++rootInorder;
	}
	if(rootInorder==endInorder && *rootInorder!=rootValue){
		throw std::exception("Invalid input");
	}
	int LeftLength=rootInorder-startInorder;
	int* leftPreorderEnd=startPreorder+leftLength;
	if(leftLength>o)
	{
		root->m_pLeft=constructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
	)
	if(leftLength<endPreorder-startPreorder)
	{
		root->m_pRight=constructCore(startPreorder+1,endPreorder,rootInorder+1,endInorder);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值