今日头条二面

1.介绍自己10min

2.介绍项目10min

3.提问:

1.写出数据库的一些选择语句。
2.ftp和http有什么区别:

以下列出了http协议和ftp协议的不同点:
主要应该说出,ftp是文件传输协议,有控制(命令链路)链路和数据链路,http是超文本传输协议。
1、HTTP协议是用来浏览网站的,而FTP是用来访问和传输文件的,FTP文件传输有点批量上传和维护网站的意思,而HTTP文件传输更多的是为终端用户提供文件传输,比如电影、图片、音乐之类。
2、HTTP 和 FTP 客户端:通常的HTTP客户端就是浏览器,而FTP服务可以通过命令行或者用户自有的图形界面客户端。
3、HTTP 头:HTTP 头包含了 metadata ,比如说最后更改的日期、编码方式、服务器名称版本还有其他的一些信息,而这些在FTP中是不存在的。
4、FTP要比HTTP早出现10年左右。
5、数据格式:FTP能传输ACSII数据或者二进制格式的数据,而HTTP只用二进制格式。
6、HTTP中的流水线:HTTP支持流水线,这就意味着客户端可以在上一个请求处理完之前,发出下一个请求,其结果就是多次请求数据之前省掉了部分服务器客户端往返时延。而FTP并没有这项支持。
7、HTTP中的动态端口:FTP一个最大的问题就是它使用两个连接,第一个连接用来发送控制指令,当接受或者发送数据的时候,又打开第二个TCP连接。而HTTP在双向传输中使用动态端口。
8、HTTP中的持久连接:对一个HTTP会话来讲,客户端可以维护一个单个的连接并使用它进行任意数量的数据传输。FTP每次有数据的需要时都创建一个新的连接。重复的创建新的连接带来的体验并不好,因为每次创建连接都必须让双方握手验证,这消耗了很多时间。
9、HTTP中的压缩算法:HTTP提供了一个在一些压缩算法中客户端和服务器共同协商选择的办法。其中gzip可以说是最有影响力的一种,而FTP中并不存在这种复杂的算法。
10、HTTP支持代理:HTTP一个很大的特点就是支持代理,这种功能是构建在协议里的,而FTP并不支持。
11、而FTP也能脱颖而出的一点是这个协议是直接面向文件级别的。这以为着FTP有例如可以通过命令列出远程服务器上的目录列表,而HTTP没有这个概念。 

3.你知道什么是cookie吗?它保存在哪里
4.你认为cookie安全吗?

cookie保存在本地,也在http包里传过去给服务器,
它可能泄露用户的一些隐私和个人信息,选择倾向等等。

5.你了解app吗?app和微信小程序的区别?

https://baijiahao.baidu.com/s?id=1607470904871676194&wfr=spider&for=pc

6.http1.0,2.0,1.1之间的区别?

https://mp.weixin.qq.com/s/GICbiyJpINrHZ41u_4zT-A 
HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。 主要区别主要体现在:
缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

HTTP/1.* 一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接;
HTTP/1.1 Pipeling解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞;
HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行;
具体如图:
HTTP2.0和HTTP1.X相比的新特性
速度明显加快。
新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。

HTTP/1.* 一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接;
HTTP/1.1 Pipeling解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞;
HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行;

为什么需要头部压缩?
假定一个页面有100个资源需要加载(这个数量对于今天的Web而言还是挺保守的), 而每一次请求都有1kb的消息头(这同样也并不少见,因为Cookie和引用等东西的存在), 则至少需要多消耗100kb来获取这些消息头。HTTP2.0可以维护一个字典,差量更新HTTP头部,大大降低因头部传输产生的流量。具体参考:HTTP/2 头部压缩技术介绍

HTTP2.0多路复用有多好?
HTTP 性能优化的关键并不在于高带宽,而是低延迟。TCP 连接会随着时间进行自我「调谐」,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。
HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。

考察算法:

1.二叉树遍历:(说真的我根本没明白啥意思,是要写个算法还是写个能跑的程序,全程很懵,到后面感到很紧张,就更写不出来了,流泪,不过最主要的还是自己平时没有特别注意练习写二叉树算法。)
递归的很好写,面试官要我写非递归的,其实也不难,
比如:

       7
     5   6
    1 2 3 4  

非递归的就每次都把前一个节点存起来,保留向上的路径就可以了,用栈很适合这样后进先出的情况。然后每次都往下,找到一个点就打印。
算法如下:

void PreOrderTraversal(BinTree BT)
{
    BinTree T = BT;
    Stack S = CreatStack(MAX_SIZE);    //创建并初始化堆栈S
    while(T || !IsEmpty(S))
    {
        while(T)        //一直向左并将沿途节点访问(打印)后压入堆栈 
        {
            printf("%d\n", T->Data);
            Push(S, T);
            T = T->Left;
        }
        if (!IsEmpty(S))
        {
            T = Pop(S);    //节点弹出堆栈
            T = T->Right;  //转向右子树
        }
    }
}

前序遍历完整代码:

#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode *Node;
typedef struct TreeNode *BinTree;

struct TreeNode
{
    char val;
    BinTree Left;
    BinTree Right;
};


/**
根据先序序列
ABDH##I##E##CF#J##G##
         A
     B     C
   D  E   F   G
 H  I ## # J  # #
##  ##    # #
**/
BinTree CreateTree()
{
    BinTree bt=NULL;
    char ch;
    scanf("%c",&ch);
    if(ch!='#')
    {
        bt=(BinTree)malloc(sizeof(BinTree));
        bt->val=ch;
        bt->Left=CreateTree();
        bt->Right = CreateTree();
    }
    return bt;
}

void PrePrint(BinTree bt)
{
    if(bt!=NULL)
    {
        printf("%c",bt->val);
        PrePrint(bt->Left);
        PrePrint(bt->Right);
    }
}

int main()
{
    BinTree bt=CreateTree();
    //printf("%c",bt->val);
    PrePrint(bt);
    return 0;
}

前序遍历非递归版本(使用了栈)

#include <iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>

using namespace std;

typedef struct TreeNode *Node;
typedef struct TreeNode *BinTree;

struct TreeNode
{
    char val;
    BinTree Left;
    BinTree Right;
};


/**
根据先序序列
ABDH##I##E##CF#J##G##
         A
     B     C
   D  E   F   G
 H  I ## # J  # #
##  ##    # #
**/
BinTree CreateTree()
{
    BinTree bt=NULL;
    char ch;
    scanf("%c",&ch);
    if(ch!='#')
    {
        bt=(BinTree)malloc(sizeof(BinTree));
        bt->val=ch;
        bt->Left=CreateTree();
        bt->Right = CreateTree();
    }
    return bt;
}

void PrePrint(BinTree bt)
{
    if(bt!=NULL)
    {
        printf("%c",bt->val);
        PrePrint(bt->Left);
        PrePrint(bt->Right);
    }
}

//非递归
void PrePrint2(BinTree root)
{
    BinTree bt=root;
    stack<BinTree> s;
    while(bt!=NULL||!s.empty())
    {
        while(bt!=NULL)
        {
            printf("%c",bt->val);
            s.push(bt);
            bt=bt->Left;
        }
        if(!s.empty())
        {
            bt=s.top();
            s.pop();
            bt=bt->Right;
        }
    }
}

int main()
{
    BinTree bt=CreateTree();
    //printf("%c",bt->val);
    PrePrint(bt);
    printf("\n");
    PrePrint2(bt);
    return 0;
}

2.简写字母:如aaaabbbbcd写为4a4bcd.

通过键盘输入一串小写字母(a~z)组成的字符串。 
请编写一个字符串压缩程序,将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串。

压缩规则:

1、仅压缩连续重复出现的字符。比如字符串”abcbc”由于无连续重复字符,压缩后的字符串还是”abcbc”。 
2、压缩字段的格式为”字符重复的次数+字符”。例如:字符串”xxxyyyyyyz”压缩后就成为”3x6yz”。

示例

输入:“cccddecc” 输出:“3c2de2c” 
输入:“adef” 输出:“adef” 
输入:“pppppppp” 输出:“8p”

主要说来就是进行字符串处理类的问题,主要涉及到:

1.字符串的输入与输出; 
2.基本常用的C语言的字符串的函数使用; 
3.对于多重情况的考虑; 
4.将数字转换成字符串并进行拼接;

这个我没完全写好,当字母出现次数大于等于10,就会有问题了。
其实就是处理数字的问题,如果大于等于10,就要用两位数来标识了。

#include <stdio.h>
int main()
{
    char a[1000]= {'\0'};
    scanf("%s",a);
    char result[1000]= {'\0'};
    int i=0;
    int j=1;
    char state;
    int length=0;
    for(i=0; i<1000&&a[i]!='\0'; i++)
    {
        state=a[i];
        if(i<999&&a[i]==a[i+1])
        {
            j+=1;
        }
        else
        {
            if(j==1)
            {
                result[length]=state;
                length+=1;
            }
            else
            {
                result[length]=j+'30';
                result[length+1]=state;
                length+=2;
            }
            j=1;
        }
    }
    for(i=0; i<1000; i++)
    {
        printf("%c   ",result[i]);
    }
    return 0;
}

处理到小于1000的数字,
也可以写为循环的形式,但是必须预先知道字符的最大总长,假设这个串全是该字符,
才能处理。

#include <stdio.h>
int main()
{
    char a[1000]= {'\0'};
    scanf("%s",a);
    char result[1000]= {'\0'};
    int i=0;
    int j=1;
    char state;
    int length=0;
    for(i=0; i<1000&&a[i]!='\0'; i++)
    {
        state=a[i];
        if(i<999&&a[i]==a[i+1])
        {
            j+=1;
        }
        else
        {
            if(j==1)
            {
                result[length]=state;
                length+=1;
            }
            else if(j<10)
            {

                result[length]=j+'30';
                result[length+1]=state;
                length+=2;
            }
            else if(j<100){
                result[length]=j/10+'30';
                result[length+1]=j%10+'30';
                result[length+2]=state;
                length+=3;

            }else if(j<1000){
                result[length]=j/10+'30';
                result[length+1]=j/100+'30';
                result[length+2]=j%100+'30';
                result[length+3]=state;
                length+=4;

            }
            j=1;
        }
    }
    for(i=0; i<1000; i++)
    {
        printf("%c   ",result[i]);
    }
    return 0;
}

一个更简洁的写法:

#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
int main()  
{  
    char str[100] = {'\0'};  
    char res[100] = {'\0'};  
    scanf("%s",str);  
    int length = strlen(str);  
    int i=0, j=0, k=0;  
    int count = 0;  
    do  
    {  
        if(i < length && str[i++] == str[j])  
            count++;  
        if(str[i] != str[j])  
        {  
            if(count <= 1)  
                res[k++] = str[j];  
            else  
            {  
                if(count > 1)  
                {  
                    char temp[10] = {'\0'};  
                    itoa(count,temp,10);  
                    strcpy(res+k,temp);  
                    k+=strlen(temp);  
                    res[k++] = str[j];  
                }  
            }  
            j = i;  
            count = 0;  
        }  
    }while(i<length);  
    res[k] = '\0';  
    printf("The result is : %s\n",res);  
    return 0;  
}  
发布了140 篇原创文章 · 获赞 114 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qinglingLS/article/details/100154632