互联网公司面试题总结

创新工场:求最长递减子序列

根据动态规划来解决

int Largest_Array(int a[],int k)
{
	int lar_end_here = 1;   //最后的长度
	int lar_so_far = 1;     //目前的最大长度
	int start=0,start1=0;
	for(int i=1;i<k;i++)
	{
		if(a[i]<a[i-1])
			lar_so_far++;
		else
		{
			lar_so_far=1;
			start1=i;
		}
		if(lar_end_here<lar_so_far)
		{
			lar_end_here = lar_so_far;
			start=start1;
		}
	}
	return lar_end_here;
}


华为:约瑟夫环

阿里巴巴:数据库优化,链表逆序+希尔排序

人人一面:对堆的理解(数据结构&操作系统两个层次)、链表有环,求交点, 不用加减乘除取模循环实现int add(int a,int b)函数,

 int main()

    chara;
 
   char*str=&a;
 
   strcpy(str,"hello");
 
   printf(str);

这小程序找毛病

 人人二面:给字符串去掉所有空格,设计模式,迭代器,证明n、n+2是质数,且n>5,那么n+1可被6整除;50亿数据去重

搜狗一面:二叉树的最大距离(编程之美原题) &先递增后递减数组的峰值,select、epoll,C++虚函数参数编译期确定函数执行期确定问题、函数重载、字节对齐语法及其实现原理、原因等等。写String类的三个控制函数,memcpy和memmove实现,设计一个内存池,被问到分配内存相差无几时怎么搞?找出两个递增数组的中位数

搜狗二面:对搜索引擎的理解,对倒排索引的理解,大数据量如何建立倒排索引,对搜狗公司的了解。

百度一面:最长匹配字串代码,大数据量用户信息数据库优化;操作系统-同步、异步、阻塞、非阻塞区别与联系,整数因子分解,使因子和最小

腾讯后台一面:给一个乱序整型数组,让找出一些符合以下条件的数:该数的前面的数都比它小,该数后面的数都比他大。

百度二面:写傻×的括号匹配的代码,二维行列递增数组的查找,即一个矩阵,任何一个右下方都比左上的数大

腾讯后台二面:

写了一个螺旋矩阵的代码就走人了

 

题目:有一个函数fun能返回0和1两个值,返回0和1的概率都是1/2,问怎么利用这个函数得到另一个函数fun2,使fun2也只能返回0和1,且返回0的概率为1/4,返回1的概率为3/4

int Fun2()  //这是1/4和3/4的。
{
	int a=Fun1()*(rand()%7+1);//a为0的概率是1/2,	为数字的概率也是1/2.产生1到8之间的数字
        if (a!=0)
	{
		if (a%2==0) //为偶数的概率是1/2*1/2
		{
			return 0;
		}
	}
	return 1;

}


int Fun_3()//分别是0.3和0.7
{

	int a1=Fun1();
	int a2=Fun1();
	int a3=Fun1();
        do{
	      int a=a1<<4+a2<<3+a3<<2+Fun()1<<1+Fun()1;///生成1——30的数字
           }while(a!=31&&a!a!=0)
	if (a%3==0)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}


 

人人:不用加减乘除取模循环实现

#include <stdio.h>

int add(int a, int b)    //迭代 
{
    int c;
    
    c = (a&b)<<1;         //保存进位 
    a ^= b;              //相加,不考虑进位,类似与半加器原理 
    
    while(c)             //两数相加直到没有进位 
    {       
            b = c;       
            c = (a&b)<<1;
            a ^= b;
    }
    
    return a;
}

int recursion_add(int a, int b)
{
    int c;
    
    if (b == 0)
       return a;
       
    c = (a&b)<<1;
    a ^= b;    
    
    return recursion_add(a, c);
}

int main()
{
    int a, b;
    while(scanf("%d%d", &a, &b) != EOF)
    {
                    printf("%d\n", add(a, b));
                    printf("%d\n", recursion_add(a, b));
    }
	return 0;
}


题目:一只青蛙一次可以跳1级台阶,也可以跳2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

 我提供三种解法。

1、递归求解:

青蛙每跳一次前,有这样三种情况:

(1)只剩1级或0级台阶了,只能跳一步或者无法再跳了,那么这条路也走到了终点,走法的种类数可以加1;

(2)可以走2级台阶;

(3)可以走1级台阶。

于是递归方法求解:

2、概率论思路求解:

首先把问题抽象成简单的数学模型,设2步台阶跳了x次,1步台阶跳了y次,那么:

2x + y = n

于是,当 x = i ,可知 x >= 0 ,且 x < n/2 (向下取整),设某时刻的 x = i ,那么有 y = n - 2 * x ,于是,总共需要走z = i + n - 2 * x 步。

这时,问题即转化为:

z步骤中,有x个两步,y个一步,相当于z个空当,由x、y去填充,那么不同填充方法的数目符合概率公式:

C(x,z) = z! / ((z-x)!x!)

即从排列z中取其中x个数的种类,x内部无序:

3、数学归纳法求解:

如果n=1,总步数f(n)=1;如果n=2,总步数f(n)=2。

另一方面,当n>=3,当前还剩的步数f(n),如果接下去跳一步,那么还剩下的步数是f(n-1);如果接下去跳两步,那么还剩下的步数是f(n-2),故:f(n)=f(n-1)+f(n-2)

现设s3=f(n),s2=f(n-2),s1=f(n-1),从时间、空间复杂度来说,这也是最简单的一种方法:



题目:二叉树节点的最大距离

如果把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两个节点之间的个数。

写一个程序求一棵二叉树中相距最远的两个节点之间的距离。

如下图所示,粗箭头的边表示最长距离:

树中相距最远的两个节点是A, B

分析可知:对于二叉树,若要两个节点U,V相距最远,有两种情况:

1,从U节点到V节点之间的路径经过根节点

2,从U节点到V节点之间的路径不经过根节点,这种情况下,U,V节点必定在根节点的左子树或者右子树上,这样就转化为求以根节点的孩子节点为根节点的二叉树中最远的两个节点间的距离

上面所说的经过根节点,是指路径中包含根节点,例如:加入上图中只有左子树FGHA, 那么最长距离的两个节点是F, A,该路径中包含根节点F,也称为经过根节点。

于是我们可以递归求解,按照二叉树的中序遍历方式遍历二叉树,在遍历的过程中寻找相距最远的两个节点。

程序描述如下:

struct Node {
    struct Node *pleft;     //左孩子
    struct Node *pright;    //右孩子
    char chValue;           //该节点的值

    int leftMaxValue;       //左子树最长距离
    int rightMaxValue;      //右子树最长距离
}LNode, *BinTree;

void findMaxLen(BinTree root, int *maxLen) {
    //遍历到叶子结点,返回
    if(root == NULL)
        return;

    //如果左子树为空,那么该节点左边最长距离为0
    if(root->pleft == NULL)
        root->leftMaxValue = 0;

    //如果右子树为空,那么该节点右边最长距离为0
    if(root->pright == NULL)
        root->rightMaxValue = 0;

    //如果左子树不为空,递归寻找左子树最长距离
    if(root->pleft != NULL)
        findMaxLen(root->pleft, maxLen);

    //如果右子树不为空,递归寻找右子树最长距离
    if(root->pright != NULL)
        findMaxLen(root->pright, maxLen);

    //计算左子树中距离根节点的最长距离
    if(root->pleft != NULL) {
        if(root->pleft->leftMaxValue > root->pleft->rightMaxValue)
            root->leftMaxValue = root->pleft->leftMaxValue + 1;
        else
            root->leftMaxValue = root->pleft->rightMaxValue + 1;
    }

    //计算右子树中距离根节点的最长距离
    if(root->pright != NULL) {
        if(root->pright->leftMaxValue > root->pright->rightMaxValue)
            root->rightMaxValue = root->pright->leftMaxValue + 1;
        else
            root->rightMaxValue = root->pright->rightMaxValue + 1;
    }

    //更新最长距离
    if(root->leftMaxValue + root->rightMaxValue > *maxLen)
        *maxLen = root->leftMaxValue + root->rightMaxValue;
}


题目:两个字符串的最大公共子串


把字符串1(长度m)横排,串2(长度n)竖排,得到一个m×n的矩阵c,矩阵的每个元素的值如下,如果m[i]=n[j],则c[j][i]=1,否则,c[j][i]=0。然后找出矩阵中连续是1的对角线最长的一个,则对角线的长度就是公共子串的长度.

 

经过改进,可以不需要构造矩阵,因为第i行如果有字母匹配,其取值仅与第i-1行相关,若m[i]=n[j],则c[j][i] =c[j-1][i-1] + 1,这样仅需要记录一个长度为m的一维数组就可以了。

#include <stdio.h>
#include <stdlib.h>

char * StringSearch( char * str1, char * str2 )
{
    int i;
    int j;
    char* ptempBuffer1;
    char* ptempBuffer2;
    char* pwork;
    char* plast;
    char* ptemp;
    char* retstr;
    int resultIndex = 0;
    int resultLength = 0;
    int str1Size = 0;
    int str2Size = 0;
    ptempBuffer1 = str1;
    while( *ptempBuffer1 != '\0' )
    {
        ptempBuffer1++;
        str1Size++;
    }
    ptempBuffer2 = str2;
    while( *ptempBuffer2 != '\0' )
    {
        ptempBuffer2++;
        str2Size++;
    }
   
    ptempBuffer1 = ( char * ) malloc( str1Size );
    pwork = ptempBuffer1;
    memset( pwork, 0, str1Size );
    ptempBuffer2 = ( char * ) malloc( str1Size );
    plast = ptempBuffer2;
    memset( plast, 0, str1Size );
    for( i = 0; i < str2Size; i++ )
    {
        for( j = 0; j < str1Size; j++ )
        {
            if( *( str1 + j ) == *( str2 + i ) )
            {
                if( j == 0 )
                {
                    *( pwork + j ) = 1;
                }
                else
                {
                    *( pwork + j ) = *( plast + j - 1 ) + 1;
                }
                if( resultLength < *( pwork + j ) )
                {
                    resultIndex = j;
                    resultLength = *( pwork + j );
                }
            }
            else
            {
                *( pwork + j ) = 0;
            }
        }
        ptemp = pwork;
        pwork = plast;
        plast = ptemp;
    }
    retstr = ( char * ) malloc( resultLength + 1 );
    memcpy( retstr, str1 + resultIndex - resultLength + 1, resultLength );
    *( retstr + resultLength ) = '\0';
    printf( "resultIndex = %d, resultLength = %d\n", resultIndex, resultLength );
    free( ptempBuffer1 );
    free( ptempBuffer2 );
    return retstr;
}

int main(int argc, char *argv[])
{
    char* ret = NULL;
    ret = StringSearch( "adbccadebbca", "edabccadece" );
    printf( "result String is %s\n", ret );
    free( ret );
    system("PAUSE"); 
    return 0;
}

为了方便,采用了两个容量为m的一维数组来保存运行中的结果,空间复杂度为m+n+2*m(保存打印输出的结果字符串可以不需要),也就是O(m+n)。由于需要事先遍历字符串得到长度,算法复杂度为m*n+ m + n,O(m*n)级别。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值