名企招聘经典面试编程题集锦[第1-10题]

声明:所有试题均来自网络。解答仅作参考,如对解答有疑问,或者有更好的解法,欢迎留言交流。

1、二叉树的深度

输入一棵二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)

形成树的一条路径,最长路径包含结点的个数为树的深度。

struct BinaryTreeNode
{
	int value;
	BinaryTreeNode* left;
	BinaryTreeNode* right;
};
int DepthOfTree(BinaryTreeNode* root)
{
	if (root == NULL)
		return 0;
	else
		return 1 + max(DepthOfTree(root->left),DepthOfTree(root->right));
}

2、二叉树中结点的最大距离

我们姑且定义"距离"为两点之间边的个数。
写一个函数,求一棵二叉树中相距最远的两个点之间的距离。

struct BinaryTreeNode
{
	int value;
	BinaryTreeNode* left;
	BinaryTreeNode* right;
};
int DepthOfTree(BinaryTreeNode* root)
{
	if (root == NULL)
		return 0;
	else
		return 1 + max(DepthOfTree(root->left),DepthOfTree(root->right));
}

int MaxDistance(BinaryTreeNode* root)
{
	if (root == NULL) 
		return 0;
	int lDepth = DepthOfTree(root->left);
	int rDepth = DepthOfTree(root->right);
	int lDistance = MaxDistance(root->left);
	int rDistance = MaxDistance(root->right);
        //最大长度取左子树的深度+右子树的深度,左子树的最大长度,
	//右子树的最大长度三者之间的最大值。
	return max(lDepth + rDepth,max(lDistance,rDistance));
}

3、把二元查找树转变成排序的双向链表

输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。

struct BinaryTreeNode
{
	int value;
	BinaryTreeNode* left;
	BinaryTreeNode* right;
};

BinaryTreeNode* Convert(BinaryTreeNode* root)
{
	BinaryTreeNode* last = NULL;
	ConvertNode(root,last);
	BinaryTreeNode* head = last;
	while(head!=NULL && head->left!=NULL)
		head = head->left;
	return head;
}

void ConvertNode(BinaryTreeNode* node,BinaryTreeNode*& last)
{
	if(node == NULL)
		return;
	if(node->left!=NULL)
		ConvertNode(node->left,last);
	node->left = last;
	if(last!=NULL)
		last->right = node;
	last = node;
	if(node->right!=NULL)
		ConvertNode(node->right,last);
}

4、设计包含min函数的栈
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。
要求函数min、push以及pop的时间复杂度都是O(1)。

template<typename T>class myStack
{
public:
	void push(const T&);
	void pop();
	const T& min()const;
private:
	stack<T> data;
	stack<T> minData;
};

template<typename T> void myStack<T>::push(const T& value)
{
	data.push(value);
	if(minData.size()==0 || value<minData.top())
		minData.push(value);
	else
		minData.push(minData.top());
}

template<typename T> void myStack<T>::pop()
{
	assert(data.size()>0 && minData.size()>0);
	data.pop();
	minData.pop();
}

template<typename T> const T& myStack<T>::min()const
{
	assert(data.size()>0 && minData.size()>0);
	return minData.top();
}

5、求子数组的最大和
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。

int FindGreatestSumOfSubArray(int* data,int length)
{
	if(data==NULL || length<1)
		throw exception("invalid parameters!");
	int sum=0;
	int max = 0x80000000;
	for(int i=0;i!=length;++i)
	{
		sum+=*(data+i);
		if(sum<0)
			sum=0;
		else if(sum>max)
			max = sum;
	}
	return max;
}

6、在二元树中找出和为某一值的所有路径

输入一个整数和一棵二元树。
从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。
打印出和与输入整数相等的所有路径。
例如 输入整数22和如下二元树
  10  
  / \   
 5   12   
/ \   
4  7
则打印出两条路径:10, 12和10, 5, 7。

struct BinaryTreeNode
{
	int value;
	BinaryTreeNode* left;
	BinaryTreeNode* right;
};

void findPath(BinaryTreeNode* root,int expectedSum)
{
	if(root==NULL)
		return;
	vector<int> path;
	int sum = 0;
	findPath(root,expectedSum,path,sum);
}

void findPath(BinaryTreeNode* root,int expectedSum,vector<int>& path,int startSum)
{
	startSum += root->value;
	path.push_back(root->value);
	bool isLeaf = root->left==NULL && root->right==NULL;
	if (startSum==expectedSum && isLeaf)
	{
		for (int i = 0;i!=path.size();++i)
			cout<<path[i]<<" ";
		cout<<endl;
	}
	else
	{
		if(root->left!=NULL)
			findPath(root->left,expectedSum,path,startSum);
		if(root->right!=NULL)
			findPath(root->right,expectedSum,path,startSum);
	} 
	startSum -= root->value;
	path.pop_back();
}
7、查找最小的k个元素
输入n个整数,输出其中最小的k个。
例如输入4,5,1,6,2,7,3和8这8个数字,则最小的4个数字为1,2,3和4。

void GetLeastNumbers(int* data,int length,int k,multiset<int>& leastNumbers)
{
	if(data==NULL || k<1 || length<k)
		return;
	for (int i=0;i!=length;++i)
	{
		if(leastNumbers.size()<k)
			leastNumbers.insert(*(data+i));
		else if(*(data+i)<*(--leastNumbers.end()))
		{
			leastNumbers.erase(--leastNumbers.end());
			leastNumbers.insert(*(data+i));
		}
	}
}

8、判断两个单向链表是否相交
给出两个单向链表的头指针,判断这俩个链表是否相交。
为了简化问题,我们假设两个链表均不带环。

bool IsIntersect(listNode* head1,listNode* head2)
{
	if(head1==NULL || head2==NULL)
		return false;
	while(head1->next!=NULL)
		head1=head1->next;
	while(head2->value!=NULL)
		head2=head2->next;
	if(head1==head2)
		return true;
	else
		return false;
}

9、判断一个整数序列是不是二元查找树的后序遍历结果
输入一个整数数组,判断该数组是不是某二叉查找树的后序遍历的结果。
如果是返回true,否则返回false。

例如输入5、7、6、9、11、10、8,返回true。如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。

bool IsResultOfPostorder(int* data,int length)
{
	if(data==NULL || length<1)
		return false;
	int root = *(data+length-1);
	int i = 0;
	for ( ;i!=length-1;++i)
	{
		if(*(data+i)>root)
			break;
	}
	for (int j =i;j!=length-1;++j)
	{
		if(*(data+j)<root)
			return false;
	}
	//判断左子树是不是二叉搜索树
	bool left = true;
	if(i>0)
		left = IsResultOfPostorder(data,i);
	//判断右子树是不是二叉搜索树
	bool right = true;
	if(i<length-1)
		right = IsResultOfPostorder(data+i,length-i-1);
	return left&&right;
}

10、翻转句子中单词的顺序。
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。

句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。
例如输入“I am a student.”,则输出“student. a am I”。

//翻转字符串
void Reverse(char* first,char* last)
{
	if(first==NULL || last==NULL)
		return;
	while (first<last)
	{
		char temp = *first;
		*first++ = *last;
		*last-- = temp;
	}
}

void ReverseSentence(char* str)
{
	if(str == NULL)
		return;
	char* first = str;
	char* last =str;
	while(*last!='\0')
		++last;
	--last;
	Reverse(first,last);
	last=first;
	while(true)
	{
		while(*last!=' ' && *last!='\0')
			++last;
		--last;
		Reverse(first,last);
		if(*(last+1)==' ')
		{
			last+=2;
			first=last;
		}
		else
			break;
	}
}

欢迎大家访问我的独立技术博客 道合|SameIdeal.com

你可能感兴趣的:(名企招聘经典面试编程题集锦[第1-10题])