面试题解答及记录

题目来源于互联网以及自己的经历,由于互联网的来源实在太多,没有一一标记,再次感谢曾经面试而分享的人

1.HTTP协议

/*
Answer:
超文本传送协议定义了浏览器怎样向万维网服务器请求万维网文档,以及服务器怎样把文档传送给浏览器。
HTTP是面向事务的应用层协议,能够在万维网上可靠地交换文件(文本、声音、视频等)
	万维网工作过程
|<---建立TCP连接---->|(TCP 80端口)
|----HTTP请求报文--->|
|<---HTTP响应报文----|
|<---释放TCP连接---->|
(1)HTTP无连接
HTTP使用了面向连接的TCP作为传输层协议,保证了数据的可靠性。HTTP不必考虑数据在传送过程中被丢弃了
怎样重传。但是HTTP本身是无连接的,虽然使用了TCP,但通信双方在交换HTTP报文前不需要先建立HTTP连接。
(2)HTTP无状态
同一个客户第二次访问同一个服务器的一个页面时,服务器的响应和第一次相同的。(可以使用cookie解决无状态)
(3)状态码
每一个请求报文后都能收到一个响应报文(HTTP版本,状态码,解析状态码简单短语)
1xx表示通知消息
2xx表示成功
3xx表示重定向
4xx表示客户差错(403Forbidden服务器已经理解请求,但是拒绝执行它;404Not Found:请求失败,请求所希望得到的资源未被在服务器上发现)
5xx表示服务器差错(502Bad Gateway:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。)
(4)文档类型
静态文档和动态文档(访问服务器时才由应用程序动态创建的)
*/

2.linux网络编程的c/s通信流程

UNIX网络编程里的TCP11种状态转移,也可以表达通信流程




3.模板与特化

特化我当时还真是忘了,因为项目开发中没有使用到,关注也就少了,果然基础很重要

为什么需要特化呢?

/*首先就是不可能写出对所有实例化的类型都合适的模版,某些情况下通用的模块对有些类型可能完全是错误的;
基于上面的原因所以会时常需要进行模块特化操作。*/
template <typename T>
int compare(const T & x, const T & y)
{
    if (x < y) return -1;
    if (y < x) return 1;
    return 0;
}
//例如这个例子,对于C字符串,比较的结果就完全是错误的
特化的三种类型转自:http://www.cnblogs.com/kyleada/archive/2011/05/23/2054479.htm

/**********************

特化的三种类型:

(1)特化为绝对类型
(2)特化为引用/指针类型
(3)特化为另一个类模板
***********************/
//普遍形式
template<class T>
class Compare
{
public:
	static bool IsEqual(const T& lh,const T& rh)
	{
		return lh==rh;
	}
};
//(1)特化为绝对类型
//为float特化
template<>
class Compare<float>
{
public:
	static bool IsEqual(const T& lh,const T& rh)
	{
		return abs(lh-rh)<10e-3;
	}
};
//(2)特化为引用/指针类型(iterator_traits)
template<class _Iterator>
struct iterator_traits
{
	//迭代器相应型别最常用的有五种:
	//分别是value_type,difference_type,reference,pointer,iterator_category
	typedef typename _Iterator::iterator_category iterator_category;
	typedef typename _Iterator::value_type        value_type;
	typedef typename _Iterator::difference_type   difference_type;
	typedef typename _Iterator::pointer           pointer;
	typedef typename _Iterator::reference         reference;
};
//为_Tp*特化
template<class _Tp>
struct iterator_traits<_Tp*>
{
	typedef random_access_iterator_tag iterator_category;
	typedef _Tp                         value_type;
	typedef ptrdiff_t                   difference_type;
	typedef _Tp*                        pointer;
	typedef _Tp&                        reference;
};
//除了T*, 我们也可以将T特化为 const T*, T&, const T&等
//IsEqual特化T*
template<class T>
class Compare<T*>
{
public:
    static bool IsEqual(const T* lh, const T* rh)
    {
        return Compare<T>::IsEqual(*lh, *rh);
    }
};
//这种特化其实是就不是一种绝对的特化, 它只是对类型做了某些限定
//但仍然保留了其一定的模板性,这种特化给我们提供了极大的方便。
//如这里, 我们就不需要对int*, float*, double*等等类型分别做特化了。

//(3)特化为另外一个类模板
//这其实是第二种方式的扩展,其实也是对类型做了某种限定,而不是绝对化为某个具体类型
//为vector<T>特化
template<class T>
class Compare<vector<T>>
{
public:
    static bool IsEqual(const vector<T>& lh, const vector<T>& rh)
    {
        if(lh.size() != rh.size()) return false;
        else
        {
            for(int i = 0; i < lh.size(); ++i)
            {
                if(lh[i] != rh[i]) return false;
            }
        }
        return true;
    }
};
//这就把IsEqual的参数限定为一种vector类型, 但具体是vector<int>还是vector<float>, 我们可以不关心,
//因为对于这两种类型,我们的处理方式是一样的,我们可以把这种方式称为“半特化”。

4.动态规划的思想

//动态规划算法的基本思想
//摘自:http://www.cnblogs.com/lvpengms/archive/2010/02/03/1663055.html
/*动态规划算法的基本思想是:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,
然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它
进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。动态规划算
法将问题的解决方案视为一系列决策的结果,与贪婪算法不同的是,在贪婪算法中,每采用一
次贪婪准则,便做出一个不可撤回的决策;而在动态规划算法中,还要考察每个最优决策序列
中是否包含一个最优决策子序列,即问题是否具有最优子结构性质。
动态规划算法的有效性依赖于待求解问题本身具有的两个重要性质:
(1)最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有
最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。
(2)子问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生
的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题
的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计
算已经计算过的子问题时,只是在表格中简 单地查看一下结果,从而获得较高的解题效率。
动态规划算法步骤:
(1)分析问题的最优解,找出最优解的性质,并刻画其结构特征;
(2)递归地定义最优值;
(3)采用自底向上的方式计算问题的最优值;
(4)根据计算最优值时得到的信息,构造最优解。*/

//动态规划和贪心算法的区别
//摘自http://zhidao.baidu.com/link?url=NsRMilVf06xD6W4G6r2GA-Wg95cxn0Wb7UsAgyxz_bwJ7z6Px6b10r7iVcYsy7ZhwbafyxCM6kT0KXUDbtb3hq
/*
相同点:
动态规划和贪心算法都是一种递推算法 
均有局部最优解来推导全局最优解 
不同点: 
贪心算法: 
(1)贪心算法中,作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一步之前的最优解则不作保留。 
(2)由(1)中的介绍,可以知道贪心法正确的条件是:每一步的最优解一定包含上一步的最优解。 
动态规划算法: 
(1)全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解 
(2)动态规划的关键是状态转移方程,即如何由以求出的局部最优解来推导全局最优解 
(3)边界条件:即最简单的,可以直接得出的局部最优解*/

//从问题树看异同
//摘自;http://blog.csdn.net/jarvischu/article/details/6056387
/*最优解问题大部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则以某种形式对树整个的遍历一遍就可以求出最优解。
贪心和动态规划本质上是对子问题树的一种修剪。两种算法要求问题都具有的一个性质就是“子问题最优性”。即,组成最优解的每一个子问题的
解,对于这个子问题本身肯定也是最优的。如果以自顶向下的方向看问题树(原问题作为根),则我们每次只需要向下遍历代表最优解的子树就
可以保证会得到整体的最优解。形象一点说,可以简单的用一个值(最优值)代表整个子树,而不用去求出这个子树所可能代表的所有值。
动态规划方法代表了这一类问题的一般解法。我们自底向上(从叶子向根)构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且
以其中的最优值作为自身的值,其它的值舍弃。动态规划的代价就取决于可选择的数目(树的叉数)和子问题的的数目(树的节点数,或者是树的高度)。
贪心算法是动态规划方法的一个特例。贪心特在,可以证明,每一个子树的根的值不取决于下面叶子的值,而只取决于当前问题的状况。换句话
说,不需要知道一个节点所有子树的情况,就可以求出这个节点的值。通常这个值都是对于当前的问题情况下,显而易见的“最优”情况。因此用
“贪心”来描述这个算法的本质。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只需要自根开始,选择最优的路,一直走到
底就可以了。这样,与动态规划相比,它的代价只取决于子问题的数目,而选择数目总为1。*/
//找钱问题
/*
现只有面额为 11元、5元、1元的三种人民币。
给定一个 数目为 money 的人民币,如何用这三种面额的人民币 找开它,且用的人民币张数最少
    如:给定 10元,我们可以有以下找法:
		2张  5元面额
        1张  5元面额+5张1元面额
        10张 1元面额
      我们 选择第一种找法。只用2张人民币。
//代码实现:http://blog.csdn.net/jarvischu/article/details/6056963
如果现在要找开 15元钱,则
        1. 根据动态规划法的解题思想,得到最优解为3张5元面额的,总共3张
        2. 根据贪心算法的解题思想,得到的近似最优解为1张11元面额的加上4张1元面额的,总共 5张*/
//个人理解:
//能用贪心的一定能用动态规划
//如果在动态规划中找到一个最优解的迭代公式可以满足贪心的要求,普通的动态规划变成贪心










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值