上次的博客已经述说了两个月秋招的各种辛苦和槽点!在找到工作之后肯定要学会分享啦~这两个月的东奔西走,我能做的最有价值的回馈当然就是分享一下各大互联网公司的面试题啦(具体公司有些忘了)!在此做了些筛选,过滤一些比较没有意义的题目.题目还包含了我的解答,有些答得并不全面,但可供大家参考,也欢迎已经工作的人来回顾一下基础.有问题的也欢迎指出来啦~(PS:篇幅有限,还有很多要等整理完下次再发O(∩_∩)O)
(1) Stringa=“abc”Stringb="abc" String c=new String("abc") Stringd="ab"+"c".他们之间用==比较的结果。
答:a==b返回true(指向同一个内存空间),与c、d则返回false(c创建了新对象,d的“+”也会创建新对象)。
(2)linux系统为什么划分内核态和用户态?
答:主要是出于安全的原因,内核态下,CPU可执行任何指令,在用户态下CPU只能执行非特权指令。当CPU处于内核态,可以随意进入用户态;而当CPU处于用户态,只能通过中断的方式进入内核态。一般程序一开始都是运行于用户态,当程序需要使用系统资源时,就必须通过调用软中断进入内核态。
(3)简单描述一下,一个请求从浏览器出发,经历了哪些过程?
答:将URL进行DNS解析→将IP和端口号合成socket→交付给tcp建立连接→发送http请求报文。
(4)判断一个单链表是否有环及环的长度。
答:
①使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出;
②记录下碰撞点p,slow、fast从该点开始,再次碰撞所走过的操作数就是环的长度s。
附:查找环的链接点:定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
判断是否存在环的程序:
bool IsExitsLoop(slist *head)
{
slist *slow = head, *fast = head;
while ( fast && fast->next )
{
slow = slow->next;
fast = fast->next->next;
if ( slow == fast ) break;
}
return !(fast == NULL || fast->next == NULL);
}
(5)两个栈实现一个队列:(主要了解队列的程序写法)
template<typenameT>//二个栈实现一个队列
classSQueue
{
public:
SQueue()
{}
~SQueue()
{}
voidAppendtail(const T&);//入队
TDeletehead();//出队
private:
LStack<T>s1,s2;
};
template<typenameT>
void SQueue<T>::Appendtail(constT&code)
{//入队元素压入栈s1中
s1.push(code);
}
template<typenameT>
TSQueue<T>::Deletehead()
{//若栈s2不空,则栈顶元素出栈,若栈s2空,则先将栈s1的元素一次出栈、入栈到s2中,此时栈s2的栈顶元素相当于队列的对头元素
if(!s2.isempty())
returns2.pop();
else
{
while(!s1.isempty())
s2.push(s1.pop());
returns2.pop();
}
}
(6)strcpy的实现代码:
char* strcpy(char * strDest,const char * strSrc)
{
if((strDest==NULL)||(strSrc==NULL)) //[1]
throw "Invalidargument(s)"; //[2]
char * strDestCopy=strDest;//[3]
while ((*strDest++=*strSrc++)!='\0');//[4]
return strDestCopy;
}
(7)判断一个数是否是2的n次方:
答:int result = (n&(n-1)==0) ? (1) : (0);
原理:如果一个数是2的n次方,那么这个数的二进制形式中只有1位为1,这样,减1之后,为1的那个位变为0,后面的位变为1,两个数相与结果为0;如果数不是2的n次方,那么减1之后再相与,结果肯定不为0.