zoukankan      html  css  js  c++  java
  • 吉比特面试准备

    吉比特面试准备

    算法知识

    1、快速排序

    快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
    (1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
    (2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
    (3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
    (4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

    2、堆排序

    堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

    hash冲突解决办法

    1.开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
    2.再哈希法
    3.链地址法(Java hashmap就是这么做的,为了好的查询,可以用红黑树)

    c++知识

    引用

    一般例子

        int a = 1;
        int &b = a;//引用
        b = 2;
        cout << a;
    

    引用的一些错误

        int &a;//引用是已经存在对象的别名,所以右边必须有一个对象
        int &b = 1;//同上,引用的初始值必须是一个对象
        double c = 1.1;
        int &d = c;//类型应该一致
    

    指针

    指针的一般用法

        int ival = 42;
        int *p = &ival;//
        cout << *p;
    

    引用与指针的区别

    1:指针本书就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象.

    2:指针无须在定义时赋初值.和其他内置类型一样,在块作用域内定义的指针如果没有被初始化.也将拥有一个不确定的值

    3:指针和引用都能提供对其他对象的间接访问,然而在具体实现细节是二者有很大的不同,其中最重要的一点就是引用本身并非一个对象.一旦定义了引用,就无法令其再绑定到另外的对象,之后每次使用这个引用都是访问他最初绑定的对象.指针和存放的地址之间就没有这种限制.给指针赋值就是令它存放一个新的地址,从而指向一个新的对象

    4:指针需要申请一段内存空间,引用不需要.

    const 限定符

    const其值定义好就不能改变

    const 函数

    const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值,这种措施主要还是为了保护数据而设置的。const 成员函数也称为常成员函数。(放在函数的后面)

    int getage() const;
    

    修饰的是返回值,表示返回的是指针所指向值是常量。(放在函数前面)

    const int * GetPosition();
    

    static 局部静态变量

    static修饰的变量,在程序第一次定义的时候初始化,并且直到程序结束的时候才被销毁,在此期间即使对象所在函数结束执行也不会对他造成影响

    例子

    int count_size()
    {
        static int siz = 0;
        return ++siz;
    }
    int main()
    {
        for(int i=1;i<=10;i++)
        {
            cout << count_size() << '
    ';
        }
        return 0;
    }
    /*
    输出结果
    1
    2
    3
    4
    5
     */
    

    智能指针

    内存泄露:动态内存分配的时候,忘记释放内存
    智能指针:share_ptr(允许多个指针访问一个对象),unique_ptr(独占所指向的对象),weak_ptr

    shared_ptr

    例子
        shared_ptr<int>p1 = make_shared<int>(42);//初始化
        auto q(p1);//拷贝
    //  auto q = p1;//赋值
    
    如何实现自动销毁所管理的对象

    我们可以认为每一个share_ptr都有一个关联的计数器,无论我们何时拷贝一个一个share_ptr,计算器都会递增,当我们给share_ptr赋一个新值或者share_ptr被销毁,计算器就会递减.一旦一个计算器变成0,他就会自动释放所管理的对象.

    unique_ptr

    一个unique_ptr"拥有"它所指的对象",与share_ptr不同.某个时刻只能有一个unique_ptr指向一个给定对象.当unique_ptr被销毁时,它所指向的对象也被销毁

    例子
        unique_ptr<int>p1 (new int(42));//初始化
        unique_ptr<int>p2(p1);//错误,不支持拷贝
        unique_ptr<int>p3;
        p3 = p2; //错误,不支持赋值
    
    如何实现unique_ptr拷贝

    我们不能拷贝或者赋值unique_ptr,但可以通过调用release和reset将指针的所以权从一个(非const)unique_ptr转移到另一个unique
    u.release():u放弃了指针的控制权,返回指针并将u职位空
    u.reset():释放u指向的对象

        unique_ptr<int>p1 (new int(42));//初始化
        unique_ptr<int>p2(p1.release());// p1.release()返回指针,并将p1置为空.
        unique_ptr<int>p3(new int(20));
        p2.reset(p3.release());//p2释放了原来指向p1的对象
    

    new和malloc的区别

    1、属性
    new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。

    2、参数
    使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。

    3、返回类型
    new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。

    4、分配失败
    new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。

    5、自定义类型
    new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
    malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。

    6、重载
    C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。

    7、内存区域
    new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

    多态

    多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态(.说了静态--函数重载,动态--虚函数)。
    C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

    虚函数

    继承的时候,对于某些函数,基类希望它的派生类自定义适应自己的版本

    深拷贝与浅拷贝

    【浅拷贝】是增加了一个指针,指向原来已经存在的内存。而【深拷贝】是增加了一个指针,并新开辟了一块空间

    构造和析构

    拷贝构造函数

    如果应该构造函数的第一个参数是自身的引用,且任何额外参数都有默认值,则此函数的拷贝构造函数

    析构函数

    class Foo{
        public:
            ~Foo();
    };
    

    为什么析构函数要用虚函数

    如果析构函数不被声明成虚函数,则编译器采用的绑定方式是静态绑定,在删除基类指针时,只会调用基类析构函数,而不调用派生类析构函数,这样就会导致基类指针指向的派生类对象析构不完全。若是将析构函数声明为虚函数,则可以解决此问题。

    当一个类有子类时,该类的析构函数必须是虚函数,原因:会有资源释放不完全的情况

    操作系统

    协程和线程的区别

    先简要说下结论:

    协同程序(coroutine)与多线程情况下的线程比较类似:有自己的堆栈,自己的局部变量,有自己的指令指针(IP,instruction pointer),但与其它协同程序共享全局变量等很多信息。

    协程(协同程序): 同一时间只能执行某个协程。开辟多个协程开销不大。协程适合对某任务进行分时处理。

    线程: 同一时间可以同时执行多个线程。开辟多条线程开销很大。线程适合多任务同时处理。

    1.协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态。协程实际上是在一个线程中,只不过每个协程对CUP进行分时,协程可以访问和使用unity的所有方法和component

    2.线程,多线程是阻塞式的,每个IO都必须开启一个新的线程,但是对于多CPU的系统应该使用thread,尤其是有大量数据运算的时刻,但是IO密集型就不适合;而且thread中不能操作unity的很多方法和component

    线程和协同程序的主要不同在于:在多处理器情况下,从概念上来讲多线程程序同时运行多个线程;而协同程序是通过协作来完成,在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只在必要时才会被挂起。

    进程通信的方式

    1. 管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
    2. 命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
    3. 消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
    4. 共享存储SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
    5. 信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
    6. 套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
    7. 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

    设计模式

    单例模式

    在有些系统中,为了节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。

    单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

    在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。

    单例模式有 3 个特点:
    单例类只有一个实例对象;
    该单例对象必须由单例类自行创建;
    单例类对外提供一个访问该单例的全局访问点;

  • 相关阅读:
    HDU 5640 King's Cake
    HDU 5615 Jam's math problem
    HDU 5610 Baby Ming and Weight lifting
    WHU1604 Play Apple 简单博弈
    HDU 1551 Cable master 二分
    CodeForces659C Tanya and Toys map
    Codeforces 960E 树dp
    gym 101485E 二分匹配
    Codeforces 961E 树状数组,思维
    Codeforces Round #473 (Div. 2) D 数学,贪心 F 线性基,模板
  • 原文地址:https://www.cnblogs.com/hh13579/p/13084894.html
Copyright © 2011-2022 走看看