笔试练习四

1.用两个栈实现一个队列


首先我们知道队列是一个先进先出的数据结构 栈是个先进后出的数据结构

所以根据这种特性我们可以分析出可以用两个栈来模拟队列这种数据结构

具体的代码实现如下:

/*
** FileName     : Double_statck_create_queue.cpp
** Author       : weikai
** Date         : 2016.5.3
*/

#include<iostream>
#include<stack>
using namespace std;

template<typename T>
class  My_queue
{
public:
	My_queue()
	{}
	~My_queue()
	{}

	void Push(const T&val)
	{
		st1.push(val);
	}
	T Pop()
	{
		if (st2.size() == 0) //st2栈为空
		{
			while (st1.size() > 0)  //将st1栈中的元素弹出压入st2栈中
			{
				st2.push(st1.top());   
				st1.pop();
			}
		}
		if (st2.size() == 0) //表示队列中没有元素了
		{
		      ... //可以给提醒或者抛出异常之后返回
		}

		T ret = st2.top();
		st2.pop();
		return ret;
	}

private:
	stack<T> st1;
	stack<T> st2;
};


int main()
{
	My_queue<int> a;
	a.Push(1);
	a.Push(2);
	cout << a.Pop() << endl;
	a.Push(3);
	a.Push(4);
	cout << a.Pop() << endl;


	getchar();
	return 0;
}

2.为string  类写赋值函数

/*
** FileName     : Mystring.cpp
** Author       : weikai
** Date         : 2016.5.3
*/

class Mystring
{
public:
	Mystring(char *val = "")
	{
		if (val == NULL)
		{
			data = new char[1];
			data[0] = '\0';
		}
		else
		{
			data = new char[strlen(val) + 1];
			strcpy(data, val);
		}
	}
	Mystring(const Mystring &rhs)
	{
		data = new char[strlen(rhs.data) + 1];
		strcpy(data, rhs.data);
	}
	Mystring& operator=(const Mystring &rhs)
	{
		if (this != &rhs)
		{
			char *tmp = new char[strlen(rhs.data)];   //这里为了异常安全使用一个临时的变量保存
			strcpy(tmp, rhs.data);                    //可以预防将data中数据释放后再次申请空间失败导致原本数据不存在
			delete data;
			data = tmp;
                        tmp=NULL;
                 }
		return *this;
	}
	//赋值函数的第二种写法  利用临时对象的生存期来实现异常安全

	//Mystring& operator=(const Mystring &rhs)
	//{
	//	if (this != &rhs)
	//	{
	//		Mystring mytmp(rhs.data);//临时对象
	//		std::swap(data, mytmp.data);  //之后临时对象中的指针指向了当前对象,在出了历史对象的作用域就会释放
	//	}
	//	return *this;
	//}
	~Mystring()
	{
		if (data != NULL)
		{
			delete []data;
		}
	
	}
	void Print()
	{
		if (data != NULL)
		{
			cout << data << endl;
		}
	}
	
private:
	char *data;
};


int main()
{

	Mystring a("123");
	Mystring b;
	b= a;
	b.Print();
	getchar();

	return 0;
}
3.在一个二维数组中每一行的数字从左到右都是递增的,每一列的数字从上到下都是递增的,现在在数组中找出一个数,希望时间复杂度尽可能小。

函数代码实现如下:

int  Find(int *arr, int rows,int colums,int x)
{
	if (arr == NULL || rows <0 || colums < 0)
	{
		return -1;
	}
	int prow =0;
	int pcol = colums - 1;

	while (prow <rows && pcol >= 0)
	{
	if (arr[prow * colums + pcol] > x)
		{
			pcol--;
		}
	else if (arr[prow *colums + pcol] < x)
		{
			prow++;
	}
		else if (arr[prow *colums + pcol] == x)
	{
		return arr[prow *colums + pcol];
	}
	else
	{
		return -1;
	}
	}
}
int main()
{
	int arr[][4] = { 1, 2, 8, 9, 2, 4, 9, 12, 4, 7, 10, 13, 6, 8, 11, 15 };
	std::cout << Find((int*)arr, 4, 4, 7) << std::endl;
	std::cout << Find((int*)arr, 4, 4, 1) << std::endl;
	std::cout << Find((int*)arr, 4, 4, 15) << std::endl;
	std::cout << Find(NULL, 4, 4, 7) << std::endl;
	getchar();
	return 0;
}

4.实现把字符串中的空格替换成%20

(PS:许多URL中有%20    而且20H 在ASCLL中就是空格,这个还是很实用的呦)

下来分析一下首先看见这个题目,一般的方法是直接将原来数组中的逐个拷贝到另一个数组拷贝的过程中将空格替换成%20  这样的时间复杂度是O(n)但是空间复杂度是O(n)    如果你想到的方法是在原来的数组中进行移动改变空格,那么时间复杂度就是O(n^2) 其实还有一个时间复杂度为O(n)     空间复杂度为O(1)的方法


就是从字符串的后边进行空格的替换,这样就不存在移动大量元素的问题


具体代码实现如下:

void Replace_Blank(char* dest,int length)
{
	if (dest == NULL || length <=0 )
	{
		return;
	}
	int old_len = 0;
	int num_blank = 0;
	int i = 0;
	while (dest[i] != '\0')
	{
		if (dest[i] == ' ')
		{
			++num_blank;
		}
		++old_len;
		++i;
	}
	int new_len = old_len + num_blank * 2;
	if (new_len > length)
	{
		return;
	}
	int new_cur = new_len;
	int old_cur = old_len;

	while (old_cur >= 0)
	{
		if (dest[old_cur] == ' ')
		{
			dest[new_cur--] = '0';
			dest[new_cur--] = '2';
			dest[new_cur--] = '%';
	}
		else
	{
			dest[new_cur--] = dest[old_cur];
		}
		old_cur--;
	}
}
int main()
{
	char str[30] = "I am a boy";
	Replace_Blank(str,30);
	//Replace_Blank(NULL, 30);
	//Replace_Blank(str, 10);
	std::cout << str << std::endl;
	getchar();
	return 0;
}

5.输入一个链表从头到尾打印链表的节点数据

实现代码如下:

typedef struct ListNode
{

	int data;
	struct ListNode *next;
}*Lnode,node;

void Push_back(Lnode &head,int val)
{
	if (head == NULL)
	{
		head = new node;
		head->data = val;
		head->next = NULL;
	}
	else
	{
		Lnode cur  = head;
		while(cur ->next != NULL)
		{
			cur = cur->next;
		}
		Lnode tmp = new node;
		tmp->data = val;
		tmp->next = NULL;

		tmp->next = cur->next;
		cur->next = tmp;
	}
}

void Print(Lnode head)
{
	if (head != NULL)
	{
		Lnode cur = head;
		
		while (cur != NULL)
		{
			cout << cur->data << " ";
			cur = cur->next;
		}
		cout << endl;
	  
	}
}

void Revese_Print(Lnode head) //利用递归实现
{
	if (head == NULL)
	{
		return;
	}
	Revese_Print(head->next);
	cout << head->data << " ";
	
} 
void Revese_Print_forStack(Lnode head)//递归的实现都是栈的,直接用栈来模拟
{
	Lnode cur = head;
	stack<int> st_tmp;
	while (cur != NULL)
	{
		st_tmp.push(cur->data);
		cur = cur->next;
	}
	while (st_tmp.size() > 0)
	{
		cout << st_tmp.top() << " ";
		st_tmp.pop();
	}

}

int main()
{

	Lnode head = NULL;
	for (int i = 0; i < 5; ++i)
	{
		Push_back(head, i);
	}

	Print(head);
	//Revese_Print(head);
	Revese_Print_forStack(head);
	getchar();
	return 0;
}

6.根据二叉树的前序和中序 还原二叉树    根据二叉树的后续和中序还原二叉树


记住几点特征:前序第一个是根节点    后续最后一个是根节点     中序中根节点 左边的是左子树 右边是右子树

实现代码如下:

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
	
};
//前序 和中序还原
   struct TreeNode * ReconstructBinTreeBy_Pre_In(std::vector<int> pre, std::vector<int>in)
   {
  	 if (pre.size() == 0 || in.size() == 0)
  	 {
  	 return NULL;
  	 }
  	 std::vector<int> pre_left;
  	 std::vector<int> in_left;
  
  	 std::vector<int> pre_right;
  	 std::vector<int> in_right;
  
  	 int val = pre[0];
  	 struct TreeNode *node = new TreeNode(val); //根节点建立
  	 std::vector<int>::size_type offset = 0;
   for (std::vector<int>::size_type i = 0; i < in.size(); ++i)
  	 {
  		 if (in[i] == val)
  		 {
  		 offset = i;
 		 break;
  	 }
   }
   for (std::vector<int>::size_type i = 0; i < pre.size(); ++i)
  	 {
  		 if (i < offset)
  		 {
  			 pre_left.push_back(pre[i + 1]); //左子树的前序
  		 in_left.push_back(in[i]); //左子树的中序
  
  		 }
  	 if (i>offset)
  	 {
  		 pre_right.push_back(pre[i]); //右子树的前序
  			 in_right.push_back(pre[i]);//右子树的中序
  		 }
  	 }
  
  	 node->left = ReconstructBinTreeBy_Pre_In(pre_left, in_left);
  	 node->right = ReconstructBinTreeBy_Pre_In(pre_right, in_right);
  	 return node;
  }
   // 中序和后序还原
  
   struct TreeNode * ReconstructBinTreeBy_In_post(std::vector<int> in, std::vector<int>post)
   {
  	 if (in.size() == 0 || post.size() == 0)
  	 {
  		 return NULL;
  	 }
  	 std::vector<int> in_left;
   std::vector<int> in_right;
  	 std::vector<int> post_left;
   std::vector<int> post_right;
  
   int val = post[post.size() - 1];
 	 struct TreeNode*node = new TreeNode(val);
 
 	 int offset = 0;
   for (int i = 0; i < (int)in.size(); ++i)
 	 {
  	 if (in[i] == val)
 		 {
 			 offset = i;
  		 break;
  	 }
  	 }
   for (int i = 0; i < (int)in.size(); ++i)
   {
  		 if (i < offset)
  	 {
  		 in_left.push_back(in[i]);
  		 post_left.push_back(post[i]);
  	 }
  	 if (i>offset)
  	 {
 		 in_right.push_back(in[i]);
  		 post_right.push_back(post[i]);
  	 }
   }
   ReconstructBinTreeBy_In_post(in_left, post_left);
  ReconstructBinTreeBy_In_post(in_right, post_right);
  	 return node;
   }
   int main()
   {
   char pre_arr[]="12473568";
   char in_arr[]="47215386";
   char post_arr[]="47258631";
  }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值