深信服面经总结

发布时间 2023-10-09 17:35:51作者: dustemoff

 

介绍项目的应用场景

 

和工业界应用的区别

 

学过什么数据结构和算法,刷过多少力扣题。

 

实现 strcpy。看我写的慢给我打断了,问我是不是没写过。答曰是,把思路给它讲了下,并说明拷贝时可能出现的覆盖问题。

 

平时编程写的多吗?出了道题目。Vim 上实现单词反转 "This is a girl"->"girl a is This",要求不能用 C++的一些接口,比 如 pop、push等,最好用纯 C 写,限时10分钟。what? 用 C++ vector 和 string 写了个 10 行左右的逻辑判断, 以为他说 的 pop、push 禁用是指不能用栈数据结构。实际他想让我写的是原地反转吧(也就是先整体反转,再逐单词反转)。

指针和引用的区别


tcp3次握手过程


怎么处理内存泄漏


原文件到可执行文件的过程


了不了解数据库(不了解)


事务相关(不了解)


求最长不重复子串的长度


深拷贝,浅拷贝区别


写一个深拷贝的例子


进程间通信方式


介绍重载重写

讲讲vector的增删操作和扩容
迭代器为什么可以遍历任何类型的数据
手撕:一串数字中找到最长的递增子序列
场景:100本书,A、B分别拿,一次可以拿1-5本,如何确保是A最后一个拿的

 

两个链表相交的判断方法 至少三种

暴力

简单的一个想法,对链表 A 中的每一个结点,我们都遍历一次链表 B 查找是否存在重复结点,第一个查找到的即第一个公共结点

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        for (ListNode *p = headA; p != nullptr; p = p->next) {
            for (ListNode *q = headB; q != nullptr; q = q->next) {
                if (p == q)
                    return p;
            }
        }
        return nullptr;
    }
};

时间复杂度:O(n^2)

空间复杂度:O(1)

哈希表

对暴力解法的一个优化方案是:先将其中一个链表存到哈希表中,此时再遍历另外一个链表查找重复结点只需 O(1)

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode *> s;
        for (ListNode *p = headA; p != nullptr; p = p->next) {
            s.emplace(p);
        }
        for (ListNode *p = headB; p != nullptr; p = p->next) {
            if (s.find(p) != s.end())
                return p;
        }
        return nullptr;
    }
};

时间复杂度:O(n)

空间复杂度:O(n)

两个链表从公共结点开始后面都是一样的,若是我们顺着链表从后向前查找,很容易就能查找到链表的公共结点(第一个不相同的结点的下一个结点即所求)

那么如何从后向前查找呢?不难想到要使用栈

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        stack<ListNode *> s1, s2;
        for (ListNode *p = headA; p != nullptr; p = p->next) {
            s1.push(p);
        }
        for (ListNode *p = headB; p != nullptr; p = p->next) {
            s2.push(p);
        }
        ListNode *ans = nullptr;
        for ( ; !s1.empty() && !s2.empty() && s1.top() == s2.top(); s1.pop(), s2.pop())
            ans = s1.top();
        return ans;
    }
};

时间复杂度:O(n)

空间复杂度:O(n)

计算长度

前面的几个方法或是时间,或是空间,不满足题目要求的 O(n)O(n)O(n) 时间复杂度,且仅用 O(1)O(1)O(1) 内存

前面栈的解法中提到,从后向前很容易查找,那么能不能从前向后呢?若是两链表等长,那自然是可以的,指针同步后移,当遇到公共结点时两指针就会相遇,但若链表不等长那就不行了,两个指针可能会指向不同的公共结点,也就无法确定一个结点是否是公共结点。

由此,我们可以想到,能不能把两个链表变成等长的链表呢?显然若两链表不等长,那么长的链表的前 n 个结点(n 是长链表比短链表多的结点数)显然不可能是公共结点。而剩余部分两链表是等长的,自然就可以按照顺序同步后移的方法查找公共结点。

不过,为确定两链表长度差,得先遍历两链表确定长度

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int size1 = 1, size2 = 1;
        ListNode *p, *q;

        if (!headA || !headB)return NULL;

        /* 计算链表长度 */
        for (p = headA; p->next != NULL; p = p->next, size1++);
        for (p = headB; p->next != NULL; p = p->next, size2++);

        /* 长链表先走,但不确定AB谁长,所以要写两个循环,但实际上有至少一个循环不会执行 */
        p = headA;
        q = headB;
        for (int i = 0; i < size1 - size2; i++, p = p->next);
        for (int i = 0; i < size2 - size1; i++, q = q->next);

        for (; p && q && p != q; p = p->next, q = q->next);

        return p;
    }
};

时间复杂度:O(n)

空间复杂度:O(1)

走过彼此的路

除了计算链表长度外,我们还可以利用 两链表长度和相等 的性质来使得两个遍历指针同步

具体做法是:先遍历其中一个链表,当到底末端后跳到另一链表,最后若两链表没有公共结点,那么两个链表指针都会走过 s1+s2个结点,同时到达两链表末尾

若有公共结点,由于最后会同时走到两链表终点,所以倒退回去,两个指针一定会在第一个公共结点处相遇
当然,若两链表等长,那确实不会跳到另一链表,不过链表等长本身指针就是同步的,同样也能找到公共结点

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *p, *q;

        for (p = headA, q = headB; p != q; ){
            if (p != NULL)
                p = p->next;
            else p = headB;
            if (q != NULL)
                q = q->next;
            else q = headA;
        }

        return p;
    }
};

时间复杂度:O(n)

空间复杂度:O(1)

手撕代码:链表反转;寻找字符串中出现次数最多的字符

 

读没读过Nginx的源码,你这个网络模型和别的有没有对比?

 

讲讲b+树和b树的区别

 

带头结点的单链表实现栈

 

做题: 合并两个有序链表

 

手撕扑克牌洗牌

 

判断一个链表是否有环

 

大数加法

 

边缘自治


进程间通信方式


写一个函数,每次返回不同的字符串。不会,后来查了下应该是用str_buffle,之前没遇到过。

 

现在有这两行代码 int a[2]={0,1};a[-1];  
编译报不报错? 不报错的话,跑起来会怎么样,要不让它cash怎么做,或者说保证一定不出问题怎么做?

 

一个Int64的数,如何求取该数二进制中1的个数,不用移位行不行?有没有更快的办法?打表的话占用内存太多了,怎么优化?

 

回到一开始的问题,int*p=a;p+=8;p[-1];会怎么样?什么结果?

 

八股问了浏览器输入网址后发生了什么,由于计网不会,没答出来,然后问了http协议,也没有答出来?,太tm菜了

 

最后手撕了两道题,一道是括号匹配问题,一道是验证ip地址是否正确。

 

问到进程如何访问内存,又没答出来,然后问JAVA虚拟机,我说虚拟机实现了跨平台,虚拟机里有解释器,各个平台都有实现不同的解释器,解释器将字节码文件转为机器码交给操作系统执行,然后问c,c++等语言能不能也一次编译,在各平台执行,我说不能,c在各个平台的代码层面就会有差异,编译后只能在当前平台使用,不知道答的对不对。

智力题:4L和6L杯子接3L水、25个人赛跑选出最快的三个人

 

智力题:种四棵树 要求任意两棵之间距离相等 没有任何限制条件